Commit 924f766a authored by Anthony Liguori's avatar Anthony Liguori
Browse files

Merge remote-tracking branch 'qmp/for-anthony' into staging

parents 93e0597e 37628f11
Loading
Loading
Loading
Loading
+40 −14
Original line number Diff line number Diff line
@@ -22,19 +22,24 @@ class QMPCapabilitiesError(QMPError):
    pass

class QEMUMonitorProtocol:
    def __init__(self, address):
    def __init__(self, address, server=False):
        """
        Create a QEMUMonitorProtocol class.

        @param address: QEMU address, can be either a unix socket path (string)
                        or a tuple in the form ( address, port ) for a TCP
                        connection
        @note No connection is established, this is done by the connect() method
        @param server: server mode listens on the socket (bool)
        @raise socket.error on socket connection errors
        @note No connection is established, this is done by the connect() or
              accept() methods
        """
        self.__events = []
        self.__address = address
        self.__sock = self.__get_sock()
        self.__sockfile = self.__sock.makefile()
        if server:
            self.__sock.bind(self.__address)
            self.__sock.listen(1)

    def __get_sock(self):
        if isinstance(self.__address, tuple):
@@ -43,7 +48,18 @@ class QEMUMonitorProtocol:
            family = socket.AF_UNIX
        return socket.socket(family, socket.SOCK_STREAM)

    def __json_read(self):
    def __negotiate_capabilities(self):
        self.__sockfile = self.__sock.makefile()
        greeting = self.__json_read()
        if greeting is None or not greeting.has_key('QMP'):
            raise QMPConnectError
        # Greeting seems ok, negotiate capabilities
        resp = self.cmd('qmp_capabilities')
        if "return" in resp:
            return greeting
        raise QMPCapabilitiesError

    def __json_read(self, only_event=False):
        while True:
            data = self.__sockfile.readline()
            if not data:
@@ -51,6 +67,7 @@ class QEMUMonitorProtocol:
            resp = json.loads(data)
            if 'event' in resp:
                self.__events.append(resp)
                if not only_event:
                    continue
            return resp

@@ -66,14 +83,19 @@ class QEMUMonitorProtocol:
        @raise QMPCapabilitiesError if fails to negotiate capabilities
        """
        self.__sock.connect(self.__address)
        greeting = self.__json_read()
        if greeting is None or not greeting.has_key('QMP'):
            raise QMPConnectError
        # Greeting seems ok, negotiate capabilities
        resp = self.cmd('qmp_capabilities')
        if "return" in resp:
            return greeting
        raise QMPCapabilitiesError
        return self.__negotiate_capabilities()

    def accept(self):
        """
        Await connection from QMP Monitor and perform capabilities negotiation.

        @return QMP greeting dict
        @raise socket.error on socket connection errors
        @raise QMPConnectError if the greeting is not received
        @raise QMPCapabilitiesError if fails to negotiate capabilities
        """
        self.__sock, _ = self.__sock.accept()
        return self.__negotiate_capabilities()

    def cmd_obj(self, qmp_cmd):
        """
@@ -106,9 +128,11 @@ class QEMUMonitorProtocol:
            qmp_cmd['id'] = id
        return self.cmd_obj(qmp_cmd)

    def get_events(self):
    def get_events(self, wait=False):
        """
        Get a list of available QMP events.

        @param wait: block until an event is available (bool)
        """
        self.__sock.setblocking(0)
        try:
@@ -118,6 +142,8 @@ class QEMUMonitorProtocol:
                # No data available
                pass
        self.__sock.setblocking(1)
        if not self.__events and wait:
            self.__json_read(only_event=True)
        return self.__events

    def clear_events(self):
+5 −4
Original line number Diff line number Diff line
@@ -740,10 +740,11 @@ ETEXI
#if defined(TARGET_I386)
    {
        .name       = "nmi",
        .args_type  = "cpu_index:i",
        .params     = "cpu",
        .help       = "inject an NMI on the given CPU",
        .mhandler.cmd = do_inject_nmi,
        .args_type  = "",
        .params     = "",
        .help       = "inject an NMI on all guest's CPUs",
        .user_print = monitor_user_noop,
        .mhandler.cmd_new = do_inject_nmi,
    },
#endif
STEXI
+12 −7
Original line number Diff line number Diff line
@@ -2544,16 +2544,21 @@ static void do_wav_capture(Monitor *mon, const QDict *qdict)
#endif

#if defined(TARGET_I386)
static void do_inject_nmi(Monitor *mon, const QDict *qdict)
static int do_inject_nmi(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
    CPUState *env;
    int cpu_index = qdict_get_int(qdict, "cpu_index");

    for (env = first_cpu; env != NULL; env = env->next_cpu)
        if (env->cpu_index == cpu_index) {
    for (env = first_cpu; env != NULL; env = env->next_cpu) {
        cpu_interrupt(env, CPU_INTERRUPT_NMI);
            break;
    }

    return 0;
}
#else
static int do_inject_nmi(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
    qerror_report(QERR_UNSUPPORTED);
    return -1;
}
#endif

+4 −0
Original line number Diff line number Diff line
@@ -200,6 +200,10 @@ static const QErrorStringTable qerror_table[] = {
        .error_fmt = QERR_UNDEFINED_ERROR,
        .desc      = "An undefined error has ocurred",
    },
    {
        .error_fmt = QERR_UNSUPPORTED,
        .desc      = "this feature or command is not currently supported",
    },
    {
        .error_fmt = QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
        .desc      = "'%(device)' uses a %(format) feature which is not "
+3 −0
Original line number Diff line number Diff line
@@ -169,6 +169,9 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_UNDEFINED_ERROR \
    "{ 'class': 'UndefinedError', 'data': {} }"

#define QERR_UNSUPPORTED \
    "{ 'class': 'Unsupported', 'data': {} }"

#define QERR_UNKNOWN_BLOCK_FORMAT_FEATURE \
    "{ 'class': 'UnknownBlockFormatFeature', 'data': { 'device': %s, 'format': %s, 'feature': %s } }"

Loading