QMP pull request
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJVUKtnAAoJEDu+7JDiTtWnOAMP/27vMOKfD4Z+kIwHKRfmZjyb 4ACjEfhndM3i3oFuOz7AYoe5vuwYbIMw7H2yeXsxXf8+88PHX4yyQ/xG1KaX0Fg/ DyO2ndDL2acRfIn/eY7K+7E4HbNONFNiCsnspdFoq7ytxpVPpanc6nCQ5//YeFPo ZA/McBl8WIfhM5uTn56q14qCiGGcz0tbQ4THpSfALlBwPfxcYzpVEmO5VN9Smbef QJ4Fy9nusydia+1fsuzm3Kgm2m0+Y2+J3o/IJFE9RmQk2UK6xEe5Vjzi10biYxVW vIc2IiDt6nAj+kjsM0GPPkwAJBojbIg9m35/tvftef/5w/UWZoqovGmx5fEAF0h5 LVA3WwuadG67LHxAS2O9qaefwSU1IcZ5ti+1YAhdwwaWs3DyYzNZ5ly0l6yN6uwX Wieyme8WAZKMqwpUmxkIGlJa5x+pW1PQB3vyf9Cyjj2tWnI7HIIoncKZ4ks70YZm MxFUefUgDtztmcknm+u3t+bN/a9w45QHRAXxCNYvaGJNwwnBrM6MPMLB7DqELUSr tdfOgkcnKZsjNKLDyINDkp7Rdepz9yn1nYPRj3ImtDdq/Bceh9CCyGG3YGot2BUR VJj4U9ouyYHKCZO9gfNsvowJDHiw0swcpU0/hZhL71tbc9CSl0y3zGm5eK2BQ9Uc Xsy9M7Oo2ou0OoT/rYUw =MGRA -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/qmp-unstable/tags/for-upstream' into staging QMP pull request # gpg: Signature made Mon May 11 14:15:19 2015 BST using RSA key ID E24ED5A7 # gpg: Good signature from "Luiz Capitulino <lcapitulino@gmail.com>" * remotes/qmp-unstable/tags/for-upstream: scripts: qmp-shell: Add verbose flag scripts: qmp-shell: add transaction subshell scripts: qmp-shell: Expand support for QMP expressions scripts: qmp-shell: refactor helpers MAINTAINERS: New maintainer for QMP and QAPI json-parser: Accept 'null' in QMP qobject: Add a special null QObject qobject: Clean up around qtype_code QJSON: Use OBJECT_CHECK Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
704eb1c099
18
MAINTAINERS
18
MAINTAINERS
@ -926,20 +926,19 @@ K: srat|SRAT
|
|||||||
T: git git://github.com/ehabkost/qemu.git numa
|
T: git git://github.com/ehabkost/qemu.git numa
|
||||||
|
|
||||||
QAPI
|
QAPI
|
||||||
M: Luiz Capitulino <lcapitulino@redhat.com>
|
M: Markus Armbruster <armbru@redhat.com>
|
||||||
M: Michael Roth <mdroth@linux.vnet.ibm.com>
|
M: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||||
S: Maintained
|
S: Supported
|
||||||
F: qapi/
|
F: qapi/
|
||||||
F: tests/qapi-schema/
|
F: tests/qapi-schema/
|
||||||
T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
|
T: git git://repo.or.cz/qemu/armbru.git qapi-next
|
||||||
|
|
||||||
QAPI Schema
|
QAPI Schema
|
||||||
M: Eric Blake <eblake@redhat.com>
|
M: Eric Blake <eblake@redhat.com>
|
||||||
M: Luiz Capitulino <lcapitulino@redhat.com>
|
|
||||||
M: Markus Armbruster <armbru@redhat.com>
|
M: Markus Armbruster <armbru@redhat.com>
|
||||||
S: Supported
|
S: Supported
|
||||||
F: qapi-schema.json
|
F: qapi-schema.json
|
||||||
T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
|
T: git git://repo.or.cz/qemu/armbru.git qapi-next
|
||||||
|
|
||||||
QObject
|
QObject
|
||||||
M: Luiz Capitulino <lcapitulino@redhat.com>
|
M: Luiz Capitulino <lcapitulino@redhat.com>
|
||||||
@ -964,13 +963,14 @@ X: qom/cpu.c
|
|||||||
F: tests/qom-test.c
|
F: tests/qom-test.c
|
||||||
|
|
||||||
QMP
|
QMP
|
||||||
M: Luiz Capitulino <lcapitulino@redhat.com>
|
M: Markus Armbruster <armbru@redhat.com>
|
||||||
S: Maintained
|
S: Supported
|
||||||
F: qmp.c
|
F: qmp.c
|
||||||
F: monitor.c
|
F: monitor.c
|
||||||
F: qmp-commands.hx
|
F: qmp-commands.hx
|
||||||
F: QMP/
|
F: docs/qmp/
|
||||||
T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
|
F: scripts/qmp/
|
||||||
|
T: git git://repo.or.cz/qemu/armbru.git qapi-next
|
||||||
|
|
||||||
SLIRP
|
SLIRP
|
||||||
M: Jan Kiszka <jan.kiszka@siemens.com>
|
M: Jan Kiszka <jan.kiszka@siemens.com>
|
||||||
|
@ -523,9 +523,6 @@ static void dump_qobject(fprintf_function func_fprintf, void *f,
|
|||||||
QDECREF(value);
|
QDECREF(value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case QTYPE_NONE:
|
|
||||||
break;
|
|
||||||
case QTYPE_MAX:
|
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -226,7 +226,7 @@ struct Property {
|
|||||||
PropertyInfo *info;
|
PropertyInfo *info;
|
||||||
int offset;
|
int offset;
|
||||||
uint8_t bitnr;
|
uint8_t bitnr;
|
||||||
uint8_t qtype;
|
qtype_code qtype;
|
||||||
int64_t defval;
|
int64_t defval;
|
||||||
int arrayoffset;
|
int arrayoffset;
|
||||||
PropertyInfo *arrayinfo;
|
PropertyInfo *arrayinfo;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Based on ideas by Avi Kivity <avi@redhat.com>
|
* Based on ideas by Avi Kivity <avi@redhat.com>
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009 Red Hat Inc.
|
* Copyright (C) 2009, 2015 Red Hat Inc.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Luiz Capitulino <lcapitulino@redhat.com>
|
* Luiz Capitulino <lcapitulino@redhat.com>
|
||||||
@ -36,7 +36,8 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
QTYPE_NONE,
|
QTYPE_NONE, /* sentinel value, no QObject has this type code */
|
||||||
|
QTYPE_QNULL,
|
||||||
QTYPE_QINT,
|
QTYPE_QINT,
|
||||||
QTYPE_QSTRING,
|
QTYPE_QSTRING,
|
||||||
QTYPE_QDICT,
|
QTYPE_QDICT,
|
||||||
@ -110,4 +111,12 @@ static inline qtype_code qobject_type(const QObject *obj)
|
|||||||
return obj->type->code;
|
return obj->type->code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern QObject qnull_;
|
||||||
|
|
||||||
|
static inline QObject *qnull(void)
|
||||||
|
{
|
||||||
|
qobject_incref(&qnull_);
|
||||||
|
return &qnull_;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* QOBJECT_H */
|
#endif /* QOBJECT_H */
|
||||||
|
10
qjson.c
10
qjson.c
@ -24,6 +24,8 @@ struct QJSON {
|
|||||||
bool omit_comma;
|
bool omit_comma;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define QJSON(obj) OBJECT_CHECK(QJSON, (obj), TYPE_QJSON)
|
||||||
|
|
||||||
static void json_emit_element(QJSON *json, const char *name)
|
static void json_emit_element(QJSON *json, const char *name)
|
||||||
{
|
{
|
||||||
/* Check whether we need to print a , before an element */
|
/* Check whether we need to print a , before an element */
|
||||||
@ -87,7 +89,7 @@ const char *qjson_get_str(QJSON *json)
|
|||||||
|
|
||||||
QJSON *qjson_new(void)
|
QJSON *qjson_new(void)
|
||||||
{
|
{
|
||||||
QJSON *json = (QJSON *)object_new(TYPE_QJSON);
|
QJSON *json = QJSON(object_new(TYPE_QJSON));
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,8 +100,7 @@ void qjson_finish(QJSON *json)
|
|||||||
|
|
||||||
static void qjson_initfn(Object *obj)
|
static void qjson_initfn(Object *obj)
|
||||||
{
|
{
|
||||||
QJSON *json = (QJSON *)object_dynamic_cast(obj, TYPE_QJSON);
|
QJSON *json = QJSON(obj);
|
||||||
assert(json);
|
|
||||||
|
|
||||||
json->str = qstring_from_str("{ ");
|
json->str = qstring_from_str("{ ");
|
||||||
json->omit_comma = true;
|
json->omit_comma = true;
|
||||||
@ -107,9 +108,8 @@ static void qjson_initfn(Object *obj)
|
|||||||
|
|
||||||
static void qjson_finalizefn(Object *obj)
|
static void qjson_finalizefn(Object *obj)
|
||||||
{
|
{
|
||||||
QJSON *json = (QJSON *)object_dynamic_cast(obj, TYPE_QJSON);
|
QJSON *json = QJSON(obj);
|
||||||
|
|
||||||
assert(json);
|
|
||||||
qobject_decref(QOBJECT(json->str));
|
qobject_decref(QOBJECT(json->str));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
util-obj-y = qint.o qstring.o qdict.o qlist.o qfloat.o qbool.o
|
util-obj-y = qnull.o qint.o qstring.o qdict.o qlist.o qfloat.o qbool.o
|
||||||
util-obj-y += qjson.o json-lexer.o json-streamer.o json-parser.o
|
util-obj-y += qjson.o json-lexer.o json-streamer.o json-parser.o
|
||||||
util-obj-y += qerror.o
|
util-obj-y += qerror.o
|
||||||
|
@ -561,6 +561,8 @@ static QObject *parse_keyword(JSONParserContext *ctxt)
|
|||||||
ret = QOBJECT(qbool_from_int(true));
|
ret = QOBJECT(qbool_from_int(true));
|
||||||
} else if (token_is_keyword(token, "false")) {
|
} else if (token_is_keyword(token, "false")) {
|
||||||
ret = QOBJECT(qbool_from_int(false));
|
ret = QOBJECT(qbool_from_int(false));
|
||||||
|
} else if (token_is_keyword(token, "null")) {
|
||||||
|
ret = qnull();
|
||||||
} else {
|
} else {
|
||||||
parse_error(ctxt, token, "invalid keyword `%s'", token_get_value(token));
|
parse_error(ctxt, token, "invalid keyword `%s'", token_get_value(token));
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -127,6 +127,9 @@ static void to_json_list_iter(QObject *obj, void *opaque)
|
|||||||
static void to_json(const QObject *obj, QString *str, int pretty, int indent)
|
static void to_json(const QObject *obj, QString *str, int pretty, int indent)
|
||||||
{
|
{
|
||||||
switch (qobject_type(obj)) {
|
switch (qobject_type(obj)) {
|
||||||
|
case QTYPE_QNULL:
|
||||||
|
qstring_append(str, "null");
|
||||||
|
break;
|
||||||
case QTYPE_QINT: {
|
case QTYPE_QINT: {
|
||||||
QInt *val = qobject_to_qint(obj);
|
QInt *val = qobject_to_qint(obj);
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
@ -260,9 +263,8 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent)
|
|||||||
}
|
}
|
||||||
case QTYPE_QERROR:
|
case QTYPE_QERROR:
|
||||||
/* XXX: should QError be emitted? */
|
/* XXX: should QError be emitted? */
|
||||||
case QTYPE_NONE:
|
|
||||||
break;
|
break;
|
||||||
case QTYPE_MAX:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
29
qobject/qnull.c
Normal file
29
qobject/qnull.c
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* QNull
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Markus Armbruster <armbru@redhat.com>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU LGPL, version 2.1
|
||||||
|
* or later. See the COPYING.LIB file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu-common.h"
|
||||||
|
#include "qapi/qmp/qobject.h"
|
||||||
|
|
||||||
|
static void qnull_destroy_obj(QObject *obj)
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const QType qnull_type = {
|
||||||
|
.code = QTYPE_QNULL,
|
||||||
|
.destroy = qnull_destroy_obj,
|
||||||
|
};
|
||||||
|
|
||||||
|
QObject qnull_ = {
|
||||||
|
.type = &qnull_type,
|
||||||
|
.refcnt = 1,
|
||||||
|
};
|
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
import qmp
|
import qmp
|
||||||
import json
|
import json
|
||||||
|
import ast
|
||||||
import readline
|
import readline
|
||||||
import sys
|
import sys
|
||||||
import pprint
|
import pprint
|
||||||
@ -51,6 +52,19 @@ class QMPShellError(Exception):
|
|||||||
class QMPShellBadPort(QMPShellError):
|
class QMPShellBadPort(QMPShellError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class FuzzyJSON(ast.NodeTransformer):
|
||||||
|
'''This extension of ast.NodeTransformer filters literal "true/false/null"
|
||||||
|
values in an AST and replaces them by proper "True/False/None" values that
|
||||||
|
Python can properly evaluate.'''
|
||||||
|
def visit_Name(self, node):
|
||||||
|
if node.id == 'true':
|
||||||
|
node.id = 'True'
|
||||||
|
if node.id == 'false':
|
||||||
|
node.id = 'False'
|
||||||
|
if node.id == 'null':
|
||||||
|
node.id = 'None'
|
||||||
|
return node
|
||||||
|
|
||||||
# TODO: QMPShell's interface is a bit ugly (eg. _fill_completion() and
|
# TODO: QMPShell's interface is a bit ugly (eg. _fill_completion() and
|
||||||
# _execute_cmd()). Let's design a better one.
|
# _execute_cmd()). Let's design a better one.
|
||||||
class QMPShell(qmp.QEMUMonitorProtocol):
|
class QMPShell(qmp.QEMUMonitorProtocol):
|
||||||
@ -59,6 +73,8 @@ class QMPShell(qmp.QEMUMonitorProtocol):
|
|||||||
self._greeting = None
|
self._greeting = None
|
||||||
self._completer = None
|
self._completer = None
|
||||||
self._pp = pp
|
self._pp = pp
|
||||||
|
self._transmode = False
|
||||||
|
self._actions = list()
|
||||||
|
|
||||||
def __get_address(self, arg):
|
def __get_address(self, arg):
|
||||||
"""
|
"""
|
||||||
@ -88,32 +104,40 @@ class QMPShell(qmp.QEMUMonitorProtocol):
|
|||||||
# clearing everything as it doesn't seem to matter
|
# clearing everything as it doesn't seem to matter
|
||||||
readline.set_completer_delims('')
|
readline.set_completer_delims('')
|
||||||
|
|
||||||
def __build_cmd(self, cmdline):
|
def __parse_value(self, val):
|
||||||
"""
|
try:
|
||||||
Build a QMP input object from a user provided command-line in the
|
return int(val)
|
||||||
following format:
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
< command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ]
|
if val.lower() == 'true':
|
||||||
"""
|
return True
|
||||||
cmdargs = cmdline.split()
|
if val.lower() == 'false':
|
||||||
qmpcmd = { 'execute': cmdargs[0], 'arguments': {} }
|
return False
|
||||||
for arg in cmdargs[1:]:
|
if val.startswith(('{', '[')):
|
||||||
opt = arg.split('=')
|
# Try first as pure JSON:
|
||||||
try:
|
try:
|
||||||
if(len(opt) > 2):
|
return json.loads(val)
|
||||||
opt[1] = '='.join(opt[1:])
|
|
||||||
value = int(opt[1])
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
if opt[1] == 'true':
|
pass
|
||||||
value = True
|
# Try once again as FuzzyJSON:
|
||||||
elif opt[1] == 'false':
|
try:
|
||||||
value = False
|
st = ast.parse(val, mode='eval')
|
||||||
elif opt[1].startswith('{'):
|
return ast.literal_eval(FuzzyJSON().visit(st))
|
||||||
value = json.loads(opt[1])
|
except SyntaxError:
|
||||||
else:
|
pass
|
||||||
value = opt[1]
|
except ValueError:
|
||||||
optpath = opt[0].split('.')
|
pass
|
||||||
parent = qmpcmd['arguments']
|
return val
|
||||||
|
|
||||||
|
def __cli_expr(self, tokens, parent):
|
||||||
|
for arg in tokens:
|
||||||
|
(key, _, val) = arg.partition('=')
|
||||||
|
if not val:
|
||||||
|
raise QMPShellError("Expected a key=value pair, got '%s'" % arg)
|
||||||
|
|
||||||
|
value = self.__parse_value(val)
|
||||||
|
optpath = key.split('.')
|
||||||
curpath = []
|
curpath = []
|
||||||
for p in optpath[:-1]:
|
for p in optpath[:-1]:
|
||||||
curpath.append(p)
|
curpath.append(p)
|
||||||
@ -126,10 +150,58 @@ class QMPShell(qmp.QEMUMonitorProtocol):
|
|||||||
if type(parent[optpath[-1]]) is dict:
|
if type(parent[optpath[-1]]) is dict:
|
||||||
raise QMPShellError('Cannot use "%s" as both leaf and non-leaf key' % '.'.join(curpath))
|
raise QMPShellError('Cannot use "%s" as both leaf and non-leaf key' % '.'.join(curpath))
|
||||||
else:
|
else:
|
||||||
raise QMPShellError('Cannot set "%s" multiple times' % opt[0])
|
raise QMPShellError('Cannot set "%s" multiple times' % key)
|
||||||
parent[optpath[-1]] = value
|
parent[optpath[-1]] = value
|
||||||
|
|
||||||
|
def __build_cmd(self, cmdline):
|
||||||
|
"""
|
||||||
|
Build a QMP input object from a user provided command-line in the
|
||||||
|
following format:
|
||||||
|
|
||||||
|
< command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ]
|
||||||
|
"""
|
||||||
|
cmdargs = cmdline.split()
|
||||||
|
|
||||||
|
# Transactional CLI entry/exit:
|
||||||
|
if cmdargs[0] == 'transaction(':
|
||||||
|
self._transmode = True
|
||||||
|
cmdargs.pop(0)
|
||||||
|
elif cmdargs[0] == ')' and self._transmode:
|
||||||
|
self._transmode = False
|
||||||
|
if len(cmdargs) > 1:
|
||||||
|
raise QMPShellError("Unexpected input after close of Transaction sub-shell")
|
||||||
|
qmpcmd = { 'execute': 'transaction',
|
||||||
|
'arguments': { 'actions': self._actions } }
|
||||||
|
self._actions = list()
|
||||||
|
return qmpcmd
|
||||||
|
|
||||||
|
# Nothing to process?
|
||||||
|
if not cmdargs:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Parse and then cache this Transactional Action
|
||||||
|
if self._transmode:
|
||||||
|
finalize = False
|
||||||
|
action = { 'type': cmdargs[0], 'data': {} }
|
||||||
|
if cmdargs[-1] == ')':
|
||||||
|
cmdargs.pop(-1)
|
||||||
|
finalize = True
|
||||||
|
self.__cli_expr(cmdargs[1:], action['data'])
|
||||||
|
self._actions.append(action)
|
||||||
|
return self.__build_cmd(')') if finalize else None
|
||||||
|
|
||||||
|
# Standard command: parse and return it to be executed.
|
||||||
|
qmpcmd = { 'execute': cmdargs[0], 'arguments': {} }
|
||||||
|
self.__cli_expr(cmdargs[1:], qmpcmd['arguments'])
|
||||||
return qmpcmd
|
return qmpcmd
|
||||||
|
|
||||||
|
def _print(self, qmp):
|
||||||
|
jsobj = json.dumps(qmp)
|
||||||
|
if self._pp is not None:
|
||||||
|
self._pp.pprint(jsobj)
|
||||||
|
else:
|
||||||
|
print str(jsobj)
|
||||||
|
|
||||||
def _execute_cmd(self, cmdline):
|
def _execute_cmd(self, cmdline):
|
||||||
try:
|
try:
|
||||||
qmpcmd = self.__build_cmd(cmdline)
|
qmpcmd = self.__build_cmd(cmdline)
|
||||||
@ -138,15 +210,16 @@ class QMPShell(qmp.QEMUMonitorProtocol):
|
|||||||
print 'command format: <command-name> ',
|
print 'command format: <command-name> ',
|
||||||
print '[arg-name1=arg1] ... [arg-nameN=argN]'
|
print '[arg-name1=arg1] ... [arg-nameN=argN]'
|
||||||
return True
|
return True
|
||||||
|
# For transaction mode, we may have just cached the action:
|
||||||
|
if qmpcmd is None:
|
||||||
|
return True
|
||||||
|
if self._verbose:
|
||||||
|
self._print(qmpcmd)
|
||||||
resp = self.cmd_obj(qmpcmd)
|
resp = self.cmd_obj(qmpcmd)
|
||||||
if resp is None:
|
if resp is None:
|
||||||
print 'Disconnected'
|
print 'Disconnected'
|
||||||
return False
|
return False
|
||||||
|
self._print(resp)
|
||||||
if self._pp is not None:
|
|
||||||
self._pp.pprint(resp)
|
|
||||||
else:
|
|
||||||
print resp
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
@ -158,6 +231,11 @@ class QMPShell(qmp.QEMUMonitorProtocol):
|
|||||||
version = self._greeting['QMP']['version']['qemu']
|
version = self._greeting['QMP']['version']['qemu']
|
||||||
print 'Connected to QEMU %d.%d.%d\n' % (version['major'],version['minor'],version['micro'])
|
print 'Connected to QEMU %d.%d.%d\n' % (version['major'],version['minor'],version['micro'])
|
||||||
|
|
||||||
|
def get_prompt(self):
|
||||||
|
if self._transmode:
|
||||||
|
return "TRANS> "
|
||||||
|
return "(QEMU) "
|
||||||
|
|
||||||
def read_exec_command(self, prompt):
|
def read_exec_command(self, prompt):
|
||||||
"""
|
"""
|
||||||
Read and execute a command.
|
Read and execute a command.
|
||||||
@ -177,6 +255,9 @@ class QMPShell(qmp.QEMUMonitorProtocol):
|
|||||||
else:
|
else:
|
||||||
return self._execute_cmd(cmdline)
|
return self._execute_cmd(cmdline)
|
||||||
|
|
||||||
|
def set_verbosity(self, verbose):
|
||||||
|
self._verbose = verbose
|
||||||
|
|
||||||
class HMPShell(QMPShell):
|
class HMPShell(QMPShell):
|
||||||
def __init__(self, address):
|
def __init__(self, address):
|
||||||
QMPShell.__init__(self, address)
|
QMPShell.__init__(self, address)
|
||||||
@ -254,7 +335,7 @@ def die(msg):
|
|||||||
def fail_cmdline(option=None):
|
def fail_cmdline(option=None):
|
||||||
if option:
|
if option:
|
||||||
sys.stderr.write('ERROR: bad command-line option \'%s\'\n' % option)
|
sys.stderr.write('ERROR: bad command-line option \'%s\'\n' % option)
|
||||||
sys.stderr.write('qemu-shell [ -p ] [ -H ] < UNIX socket path> | < TCP address:port >\n')
|
sys.stderr.write('qemu-shell [ -v ] [ -p ] [ -H ] < UNIX socket path> | < TCP address:port >\n')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@ -262,6 +343,7 @@ def main():
|
|||||||
qemu = None
|
qemu = None
|
||||||
hmp = False
|
hmp = False
|
||||||
pp = None
|
pp = None
|
||||||
|
verbose = False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for arg in sys.argv[1:]:
|
for arg in sys.argv[1:]:
|
||||||
@ -273,6 +355,8 @@ def main():
|
|||||||
if pp is not None:
|
if pp is not None:
|
||||||
fail_cmdline(arg)
|
fail_cmdline(arg)
|
||||||
pp = pprint.PrettyPrinter(indent=4)
|
pp = pprint.PrettyPrinter(indent=4)
|
||||||
|
elif arg == "-v":
|
||||||
|
verbose = True
|
||||||
else:
|
else:
|
||||||
if qemu is not None:
|
if qemu is not None:
|
||||||
fail_cmdline(arg)
|
fail_cmdline(arg)
|
||||||
@ -297,7 +381,8 @@ def main():
|
|||||||
die('Could not connect to %s' % addr)
|
die('Could not connect to %s' % addr)
|
||||||
|
|
||||||
qemu.show_banner()
|
qemu.show_banner()
|
||||||
while qemu.read_exec_command('(QEMU) '):
|
qemu.set_verbosity(verbose)
|
||||||
|
while qemu.read_exec_command(qemu.get_prompt()):
|
||||||
pass
|
pass
|
||||||
qemu.close()
|
qemu.close()
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright IBM, Corp. 2009
|
* Copyright IBM, Corp. 2009
|
||||||
* Copyright (c) 2013 Red Hat Inc.
|
* Copyright (c) 2013, 2015 Red Hat Inc.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Anthony Liguori <aliguori@us.ibm.com>
|
* Anthony Liguori <aliguori@us.ibm.com>
|
||||||
@ -1005,6 +1005,7 @@ static void keyword_literal(void)
|
|||||||
{
|
{
|
||||||
QObject *obj;
|
QObject *obj;
|
||||||
QBool *qbool;
|
QBool *qbool;
|
||||||
|
QObject *null;
|
||||||
QString *str;
|
QString *str;
|
||||||
|
|
||||||
obj = qobject_from_json("true");
|
obj = qobject_from_json("true");
|
||||||
@ -1041,7 +1042,7 @@ static void keyword_literal(void)
|
|||||||
g_assert(qbool_get_int(qbool) == 0);
|
g_assert(qbool_get_int(qbool) == 0);
|
||||||
|
|
||||||
QDECREF(qbool);
|
QDECREF(qbool);
|
||||||
|
|
||||||
obj = qobject_from_jsonf("%i", true);
|
obj = qobject_from_jsonf("%i", true);
|
||||||
g_assert(obj != NULL);
|
g_assert(obj != NULL);
|
||||||
g_assert(qobject_type(obj) == QTYPE_QBOOL);
|
g_assert(qobject_type(obj) == QTYPE_QBOOL);
|
||||||
@ -1050,6 +1051,16 @@ static void keyword_literal(void)
|
|||||||
g_assert(qbool_get_int(qbool) != 0);
|
g_assert(qbool_get_int(qbool) != 0);
|
||||||
|
|
||||||
QDECREF(qbool);
|
QDECREF(qbool);
|
||||||
|
|
||||||
|
obj = qobject_from_json("null");
|
||||||
|
g_assert(obj != NULL);
|
||||||
|
g_assert(qobject_type(obj) == QTYPE_QNULL);
|
||||||
|
|
||||||
|
null = qnull();
|
||||||
|
g_assert(null == obj);
|
||||||
|
|
||||||
|
qobject_decref(obj);
|
||||||
|
qobject_decref(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct LiteralQDictEntry LiteralQDictEntry;
|
typedef struct LiteralQDictEntry LiteralQDictEntry;
|
||||||
|
Loading…
Reference in New Issue
Block a user