| 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 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 169 self.protocol = "human" | 169 self.protocol = "human" |
| 170 | 170 |
| 171 # Find the initial (qemu) prompt | 171 # Find the initial (qemu) prompt |
| 172 s, o = self._read_up_to_qemu_prompt(20) | 172 s, o = self._read_up_to_qemu_prompt(20) |
| 173 if not s: | 173 if not s: |
| 174 raise MonitorProtocolError("Could not find (qemu) prompt " | 174 raise MonitorProtocolError("Could not find (qemu) prompt " |
| 175 "after connecting to monitor. " | 175 "after connecting to monitor. " |
| 176 "Output so far: %r" % o) | 176 "Output so far: %r" % o) |
| 177 | 177 |
| 178 # Save the output of 'help' for future use | 178 # Save the output of 'help' for future use |
| 179 self._help_str = self.cmd("help") | 179 self._help_str = self.cmd("help", debug=False) |
| 180 | 180 |
| 181 except MonitorError, e: | 181 except MonitorError, e: |
| 182 if suppress_exceptions: | 182 if suppress_exceptions: |
| 183 logging.warn(e) | 183 logging.warn(e) |
| 184 else: | 184 else: |
| 185 raise | 185 raise |
| 186 | 186 |
| 187 | 187 |
| 188 # Private methods | 188 # Private methods |
| 189 | 189 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 except socket.error, e: | 221 except socket.error, e: |
| 222 raise MonitorSocketError("Could not send monitor command %r" % | 222 raise MonitorSocketError("Could not send monitor command %r" % |
| 223 cmd, e) | 223 cmd, e) |
| 224 | 224 |
| 225 finally: | 225 finally: |
| 226 self._lock.release() | 226 self._lock.release() |
| 227 | 227 |
| 228 | 228 |
| 229 # Public methods | 229 # Public methods |
| 230 | 230 |
| 231 def cmd(self, command, timeout=20): | 231 def cmd(self, command, timeout=20, debug=True): |
| 232 """ | 232 """ |
| 233 Send command to the monitor. | 233 Send command to the monitor. |
| 234 | 234 |
| 235 @param command: Command to send 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 | 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 |
| 237 @return: Output received from the monitor | 238 @return: Output received from the monitor |
| 238 @raise MonitorLockError: Raised if the lock cannot be acquired | 239 @raise MonitorLockError: Raised if the lock cannot be acquired |
| 239 @raise MonitorSocketError: Raised if a socket error occurs | 240 @raise MonitorSocketError: Raised if a socket error occurs |
| 240 @raise MonitorProtocolError: Raised if the (qemu) prompt cannot be | 241 @raise MonitorProtocolError: Raised if the (qemu) prompt cannot be |
| 241 found after sending the command | 242 found after sending the command |
| 242 """ | 243 """ |
| 244 if debug: |
| 245 logging.debug("(monitor %s) Sending command '%s'", |
| 246 self.name, command) |
| 243 if not self._acquire_lock(20): | 247 if not self._acquire_lock(20): |
| 244 raise MonitorLockError("Could not acquire exclusive lock to send " | 248 raise MonitorLockError("Could not acquire exclusive lock to send " |
| 245 "monitor command '%s'" % command) | 249 "monitor command '%s'" % command) |
| 246 | 250 |
| 247 try: | 251 try: |
| 248 # Read any data that might be available | 252 # Read any data that might be available |
| 249 self._recvall() | 253 self._recvall() |
| 250 # Send command | 254 # Send command |
| 251 self._send(command) | 255 self._send(command) |
| 252 # Read output | 256 # Read output |
| 253 s, o = self._read_up_to_qemu_prompt(timeout) | 257 s, o = self._read_up_to_qemu_prompt(timeout) |
| 254 # Remove command echo from output | 258 # Remove command echo from output |
| 255 o = "\n".join(o.splitlines()[1:]) | 259 o = "\n".join(o.splitlines()[1:]) |
| 256 # Report success/failure | 260 # Report success/failure |
| 257 if s: | 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) |
| 258 return o | 268 return o |
| 259 else: | 269 else: |
| 260 msg = ("Could not find (qemu) prompt after command '%s'. " | 270 msg = ("Could not find (qemu) prompt after command '%s'. " |
| 261 "Output so far: %r" % (command, o)) | 271 "Output so far: %r" % (command, o)) |
| 262 raise MonitorProtocolError(msg) | 272 raise MonitorProtocolError(msg) |
| 263 | 273 |
| 264 finally: | 274 finally: |
| 265 self._lock.release() | 275 self._lock.release() |
| 266 | 276 |
| 267 | 277 |
| 268 def verify_responsive(self): | 278 def verify_responsive(self): |
| 269 """ | 279 """ |
| 270 Make sure the monitor is responsive by sending a command. | 280 Make sure the monitor is responsive by sending a command. |
| 271 """ | 281 """ |
| 272 self.cmd("info status") | 282 self.cmd("info status", debug=False) |
| 273 | 283 |
| 274 | 284 |
| 275 # Command wrappers | 285 # Command wrappers |
| 276 # Notes: | 286 # Notes: |
| 277 # - All of the following commands raise exceptions in a similar manner to | 287 # - All of the following commands raise exceptions in a similar manner to |
| 278 # cmd(). | 288 # cmd(). |
| 279 # - A command wrapper should use self._help_str if it requires information | 289 # - A command wrapper should use self._help_str if it requires information |
| 280 # about the monitor's capabilities. | 290 # about the monitor's capabilities. |
| 281 | 291 |
| 282 def quit(self): | 292 def quit(self): |
| (...skipping 10 matching lines...) Expand all Loading... |
| 293 return self.cmd("info %s" % what) | 303 return self.cmd("info %s" % what) |
| 294 | 304 |
| 295 | 305 |
| 296 def query(self, what): | 306 def query(self, what): |
| 297 """ | 307 """ |
| 298 Alias for info. | 308 Alias for info. |
| 299 """ | 309 """ |
| 300 return self.info(what) | 310 return self.info(what) |
| 301 | 311 |
| 302 | 312 |
| 303 def screendump(self, filename): | 313 def screendump(self, filename, debug=True): |
| 304 """ | 314 """ |
| 305 Request a screendump. | 315 Request a screendump. |
| 306 | 316 |
| 307 @param filename: Location for the screendump | 317 @param filename: Location for the screendump |
| 308 @return: The command's output | 318 @return: The command's output |
| 309 """ | 319 """ |
| 310 return self.cmd("screendump %s" % filename) | 320 return self.cmd(command="screendump %s" % filename, debug=debug) |
| 311 | 321 |
| 312 | 322 |
| 313 def migrate(self, uri, full_copy=False, incremental_copy=False, wait=False): | 323 def migrate(self, uri, full_copy=False, incremental_copy=False, wait=False): |
| 314 """ | 324 """ |
| 315 Migrate. | 325 Migrate. |
| 316 | 326 |
| 317 @param uri: destination URI | 327 @param uri: destination URI |
| 318 @param full_copy: If true, migrate with full disk copy | 328 @param full_copy: If true, migrate with full disk copy |
| 319 @param incremental_copy: If true, migrate with incremental disk copy | 329 @param incremental_copy: If true, migrate with incremental disk copy |
| 320 @param wait: If true, wait for completion | 330 @param wait: If true, wait for completion |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 507 for obj in self._read_objects(): | 517 for obj in self._read_objects(): |
| 508 if isinstance(obj, dict): | 518 if isinstance(obj, dict): |
| 509 if id is not None and obj.get("id") != id: | 519 if id is not None and obj.get("id") != id: |
| 510 continue | 520 continue |
| 511 if "return" in obj or "error" in obj: | 521 if "return" in obj or "error" in obj: |
| 512 return obj | 522 return obj |
| 513 | 523 |
| 514 | 524 |
| 515 # Public methods | 525 # Public methods |
| 516 | 526 |
| 517 def cmd(self, cmd, args=None, timeout=20): | 527 def cmd(self, cmd, args=None, timeout=20, debug=True): |
| 518 """ | 528 """ |
| 519 Send a QMP monitor command and return the response. | 529 Send a QMP monitor command and return the response. |
| 520 | 530 |
| 521 Note: an id is automatically assigned to the command and the response | 531 Note: an id is automatically assigned to the command and the response |
| 522 is checked for the presence of the same id. | 532 is checked for the presence of the same id. |
| 523 | 533 |
| 524 @param cmd: Command to send | 534 @param cmd: Command to send |
| 525 @param args: A dict containing command arguments, or None | 535 @param args: A dict containing command arguments, or None |
| 526 @param timeout: Time duration to wait for response | 536 @param timeout: Time duration to wait for response |
| 527 @return: The response received | 537 @return: The response received |
| 528 @raise MonitorLockError: Raised if the lock cannot be acquired | 538 @raise MonitorLockError: Raised if the lock cannot be acquired |
| 529 @raise MonitorSocketError: Raised if a socket error occurs | 539 @raise MonitorSocketError: Raised if a socket error occurs |
| 530 @raise MonitorProtocolError: Raised if no response is received | 540 @raise MonitorProtocolError: Raised if no response is received |
| 531 @raise QMPCmdError: Raised if the response is an error message | 541 @raise QMPCmdError: Raised if the response is an error message |
| 532 (the exception's args are (cmd, args, data) where data is the | 542 (the exception's args are (cmd, args, data) where data is the |
| 533 error data) | 543 error data) |
| 534 """ | 544 """ |
| 545 if debug: |
| 546 logging.debug("(monitor %s) Sending command '%s'", |
| 547 self.name, cmd) |
| 535 if not self._acquire_lock(20): | 548 if not self._acquire_lock(20): |
| 536 raise MonitorLockError("Could not acquire exclusive lock to send " | 549 raise MonitorLockError("Could not acquire exclusive lock to send " |
| 537 "QMP command '%s'" % cmd) | 550 "QMP command '%s'" % cmd) |
| 538 | 551 |
| 539 try: | 552 try: |
| 540 # Read any data that might be available | 553 # Read any data that might be available |
| 541 self._read_objects() | 554 self._read_objects() |
| 542 # Send command | 555 # Send command |
| 543 id = kvm_utils.generate_random_string(8) | 556 id = kvm_utils.generate_random_string(8) |
| 544 self._send(json.dumps(self._build_cmd(cmd, args, id)) + "\n") | 557 self._send(json.dumps(self._build_cmd(cmd, args, id)) + "\n") |
| 545 # Read response | 558 # Read response |
| 546 r = self._get_response(id, timeout) | 559 r = self._get_response(id, timeout) |
| 547 if r is None: | 560 if r is None: |
| 548 raise MonitorProtocolError("Received no response to QMP " | 561 raise MonitorProtocolError("Received no response to QMP " |
| 549 "command '%s', or received a " | 562 "command '%s', or received a " |
| 550 "response with an incorrect id" | 563 "response with an incorrect id" |
| 551 % cmd) | 564 % cmd) |
| 552 if "return" in r: | 565 if "return" in r: |
| 566 if debug and r["return"]: |
| 567 logging.debug("(monitor %s) " |
| 568 "Response to '%s'", self.name, cmd) |
| 569 o = str(r["return"]) |
| 570 for l in o.splitlines(): |
| 571 logging.debug("(monitor %s) %s", self.name, l) |
| 553 return r["return"] | 572 return r["return"] |
| 554 if "error" in r: | 573 if "error" in r: |
| 555 raise QMPCmdError(cmd, args, r["error"]) | 574 raise QMPCmdError(cmd, args, r["error"]) |
| 556 | 575 |
| 557 finally: | 576 finally: |
| 558 self._lock.release() | 577 self._lock.release() |
| 559 | 578 |
| 560 | 579 |
| 561 def cmd_raw(self, data, timeout=20): | 580 def cmd_raw(self, data, timeout=20): |
| 562 """ | 581 """ |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 621 @raise MonitorSocketError: Raised if a socket error occurs | 640 @raise MonitorSocketError: Raised if a socket error occurs |
| 622 @raise MonitorProtocolError: Raised if no response is received | 641 @raise MonitorProtocolError: Raised if no response is received |
| 623 """ | 642 """ |
| 624 return self.cmd_obj(self._build_cmd(cmd, args, id), timeout) | 643 return self.cmd_obj(self._build_cmd(cmd, args, id), timeout) |
| 625 | 644 |
| 626 | 645 |
| 627 def verify_responsive(self): | 646 def verify_responsive(self): |
| 628 """ | 647 """ |
| 629 Make sure the monitor is responsive by sending a command. | 648 Make sure the monitor is responsive by sending a command. |
| 630 """ | 649 """ |
| 631 self.cmd("query-status") | 650 self.cmd(cmd="query-status", debug=False) |
| 632 | 651 |
| 633 | 652 |
| 634 def get_events(self): | 653 def get_events(self): |
| 635 """ | 654 """ |
| 636 Return a list of the asynchronous events received since the last | 655 Return a list of the asynchronous events received since the last |
| 637 clear_events() call. | 656 clear_events() call. |
| 638 | 657 |
| 639 @return: A list of events (the objects returned have an "event" key) | 658 @return: A list of events (the objects returned have an "event" key) |
| 640 @raise MonitorLockError: Raised if the lock cannot be acquired | 659 @raise MonitorLockError: Raised if the lock cannot be acquired |
| 641 """ | 660 """ |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 699 return self.cmd("query-%s" % what) | 718 return self.cmd("query-%s" % what) |
| 700 | 719 |
| 701 | 720 |
| 702 def query(self, what): | 721 def query(self, what): |
| 703 """ | 722 """ |
| 704 Alias for info. | 723 Alias for info. |
| 705 """ | 724 """ |
| 706 return self.info(what) | 725 return self.info(what) |
| 707 | 726 |
| 708 | 727 |
| 709 def screendump(self, filename): | 728 def screendump(self, filename, debug=True): |
| 710 """ | 729 """ |
| 711 Request a screendump. | 730 Request a screendump. |
| 712 | 731 |
| 713 @param filename: Location for the screendump | 732 @param filename: Location for the screendump |
| 714 @return: The response to the command | 733 @return: The response to the command |
| 715 """ | 734 """ |
| 716 args = {"filename": filename} | 735 args = {"filename": filename} |
| 717 return self.cmd("screendump", args) | 736 return self.cmd(cmd="screendump", args=args, debug=debug) |
| 718 | 737 |
| 719 | 738 |
| 720 def migrate(self, uri, full_copy=False, incremental_copy=False, wait=False): | 739 def migrate(self, uri, full_copy=False, incremental_copy=False, wait=False): |
| 721 """ | 740 """ |
| 722 Migrate. | 741 Migrate. |
| 723 | 742 |
| 724 @param uri: destination URI | 743 @param uri: destination URI |
| 725 @param full_copy: If true, migrate with full disk copy | 744 @param full_copy: If true, migrate with full disk copy |
| 726 @param incremental_copy: If true, migrate with incremental disk copy | 745 @param incremental_copy: If true, migrate with incremental disk copy |
| 727 @param wait: If true, wait for completion | 746 @param wait: If true, wait for completion |
| 728 @return: The response to the command | 747 @return: The response to the command |
| 729 """ | 748 """ |
| 730 args = {"uri": uri, | 749 args = {"uri": uri, |
| 731 "blk": full_copy, | 750 "blk": full_copy, |
| 732 "inc": incremental_copy} | 751 "inc": incremental_copy} |
| 733 return self.cmd("migrate", args) | 752 return self.cmd("migrate", args) |
| 734 | 753 |
| 735 | 754 |
| 736 def migrate_set_speed(self, value): | 755 def migrate_set_speed(self, value): |
| 737 """ | 756 """ |
| 738 Set maximum speed (in bytes/sec) for migrations. | 757 Set maximum speed (in bytes/sec) for migrations. |
| 739 | 758 |
| 740 @param value: Speed in bytes/sec | 759 @param value: Speed in bytes/sec |
| 741 @return: The response to the command | 760 @return: The response to the command |
| 742 """ | 761 """ |
| 743 args = {"value": value} | 762 args = {"value": value} |
| 744 return self.cmd("migrate_set_speed", args) | 763 return self.cmd("migrate_set_speed", args) |
| OLD | NEW |