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

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.4 ! root      131:     def get_events(self, wait=False):
1.1.1.3   root      132:         """
                    133:         Get a list of available QMP events.
1.1.1.4 ! root      134: 
        !           135:         @param wait: block until an event is available (bool)
1.1.1.3   root      136:         """
                    137:         self.__sock.setblocking(0)
1.1       root      138:         try:
1.1.1.3   root      139:             self.__json_read()
                    140:         except socket.error, err:
                    141:             if err[0] == errno.EAGAIN:
                    142:                 # No data available
                    143:                 pass
                    144:         self.__sock.setblocking(1)
1.1.1.4 ! root      145:         if not self.__events and wait:
        !           146:             self.__json_read(only_event=True)
1.1.1.3   root      147:         return self.__events
                    148: 
                    149:     def clear_events(self):
                    150:         """
                    151:         Clear current list of pending events.
                    152:         """
                    153:         self.__events = []
                    154: 
                    155:     def close(self):
                    156:         self.__sock.close()
                    157:         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.