Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Side by Side Diff: client/tests/kvm/kvm_monitor.py

Issue 6246035: Merge remote branch 'cros/upstream' into master (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/autotest.git@master
Patch Set: patch Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698