Annotation of qemu/QMP/qmp.py, revision 1.1.1.5

1.1       root        1: # QEMU Monitor Protocol Python class
                      2: # 
1.1.1.3   root        3: # Copyright (C) 2009, 2010 Red Hat Inc.
1.1       root        4: #
                      5: # Authors:
                      6: #  Luiz Capitulino <[email protected]>
                      7: #
                      8: # This work is licensed under the terms of the GNU GPL, version 2.  See
                      9: # the COPYING file in the top-level directory.
                     10: 
1.1.1.3   root       11: import json
                     12: import errno
                     13: import socket
1.1       root       14: 
                     15: class QMPError(Exception):
                     16:     pass
                     17: 
                     18: class QMPConnectError(QMPError):
                     19:     pass
                     20: 
1.1.1.3   root       21: class QMPCapabilitiesError(QMPError):
                     22:     pass
                     23: 
1.1       root       24: class QEMUMonitorProtocol:
1.1.1.4   root       25:     def __init__(self, address, server=False):
1.1.1.3   root       26:         """
                     27:         Create a QEMUMonitorProtocol class.
                     28: 
                     29:         @param address: QEMU address, can be either a unix socket path (string)
                     30:                         or a tuple in the form ( address, port ) for a TCP
                     31:                         connection
1.1.1.4   root       32:         @param server: server mode listens on the socket (bool)
                     33:         @raise socket.error on socket connection errors
                     34:         @note No connection is established, this is done by the connect() or
                     35:               accept() methods
1.1.1.3   root       36:         """
                     37:         self.__events = []
                     38:         self.__address = address
                     39:         self.__sock = self.__get_sock()
1.1.1.4   root       40:         if server:
                     41:             self.__sock.bind(self.__address)
                     42:             self.__sock.listen(1)
1.1.1.3   root       43: 
                     44:     def __get_sock(self):
                     45:         if isinstance(self.__address, tuple):
                     46:             family = socket.AF_INET
                     47:         else:
                     48:             family = socket.AF_UNIX
                     49:         return socket.socket(family, socket.SOCK_STREAM)
1.1       root       50: 
1.1.1.4   root       51:     def __negotiate_capabilities(self):
                     52:         self.__sockfile = self.__sock.makefile()
                     53:         greeting = self.__json_read()
                     54:         if greeting is None or not greeting.has_key('QMP'):
                     55:             raise QMPConnectError
                     56:         # Greeting seems ok, negotiate capabilities
                     57:         resp = self.cmd('qmp_capabilities')
                     58:         if "return" in resp:
                     59:             return greeting
                     60:         raise QMPCapabilitiesError
                     61: 
                     62:     def __json_read(self, only_event=False):
1.1.1.3   root       63:         while True:
                     64:             data = self.__sockfile.readline()
                     65:             if not data:
                     66:                 return
                     67:             resp = json.loads(data)
                     68:             if 'event' in resp:
                     69:                 self.__events.append(resp)
1.1.1.4   root       70:                 if not only_event:
                     71:                     continue
1.1.1.3   root       72:             return resp
1.1       root       73: 
1.1.1.3   root       74:     error = socket.error
1.1       root       75: 
1.1.1.3   root       76:     def connect(self):
                     77:         """
                     78:         Connect to the QMP Monitor and perform capabilities negotiation.
1.1       root       79: 
1.1.1.3   root       80:         @return QMP greeting dict
                     81:         @raise socket.error on socket connection errors
                     82:         @raise QMPConnectError if the greeting is not received
                     83:         @raise QMPCapabilitiesError if fails to negotiate capabilities
                     84:         """
                     85:         self.__sock.connect(self.__address)
1.1.1.4   root       86:         return self.__negotiate_capabilities()
                     87: 
                     88:     def accept(self):
                     89:         """
                     90:         Await connection from QMP Monitor and perform capabilities negotiation.
                     91: 
                     92:         @return QMP greeting dict
                     93:         @raise socket.error on socket connection errors
                     94:         @raise QMPConnectError if the greeting is not received
                     95:         @raise QMPCapabilitiesError if fails to negotiate capabilities
                     96:         """
                     97:         self.__sock, _ = self.__sock.accept()
                     98:         return self.__negotiate_capabilities()
1.1.1.3   root       99: 
                    100:     def cmd_obj(self, qmp_cmd):
                    101:         """
                    102:         Send a QMP command to the QMP Monitor.
                    103: 
                    104:         @param qmp_cmd: QMP command to be sent as a Python dict
                    105:         @return QMP response as a Python dict or None if the connection has
                    106:                 been closed
                    107:         """
                    108:         try:
                    109:             self.__sock.sendall(json.dumps(qmp_cmd))
                    110:         except socket.error, err:
                    111:             if err[0] == errno.EPIPE:
                    112:                 return
                    113:             raise socket.error(err)
                    114:         return self.__json_read()
1.1       root      115: 
1.1.1.3   root      116:     def cmd(self, name, args=None, id=None):
                    117:         """
                    118:         Build a QMP command and send it to the QMP Monitor.
                    119: 
                    120:         @param name: command name (string)
                    121:         @param args: command arguments (dict)
                    122:         @param id: command id (dict, list, string or int)
                    123:         """
                    124:         qmp_cmd = { 'execute': name }
                    125:         if args:
                    126:             qmp_cmd['arguments'] = args
                    127:         if id:
                    128:             qmp_cmd['id'] = id
                    129:         return self.cmd_obj(qmp_cmd)
                    130: 
1.1.1.5 ! root      131:     def command(self, cmd, **kwds):
        !           132:         ret = self.cmd(cmd, kwds)
        !           133:         if ret.has_key('error'):
        !           134:             raise Exception(ret['error']['desc'])
        !           135:         return ret['return']
        !           136: 
1.1.1.4   root      137:     def get_events(self, wait=False):
1.1.1.3   root      138:         """
                    139:         Get a list of available QMP events.
1.1.1.4   root      140: 
                    141:         @param wait: block until an event is available (bool)
1.1.1.3   root      142:         """
                    143:         self.__sock.setblocking(0)
1.1       root      144:         try:
1.1.1.3   root      145:             self.__json_read()
                    146:         except socket.error, err:
                    147:             if err[0] == errno.EAGAIN:
                    148:                 # No data available
                    149:                 pass
                    150:         self.__sock.setblocking(1)
1.1.1.4   root      151:         if not self.__events and wait:
                    152:             self.__json_read(only_event=True)
1.1.1.3   root      153:         return self.__events
                    154: 
                    155:     def clear_events(self):
                    156:         """
                    157:         Clear current list of pending events.
                    158:         """
                    159:         self.__events = []
                    160: 
                    161:     def close(self):
                    162:         self.__sock.close()
                    163:         self.__sockfile.close()

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.