qapi: Convert query-spice

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
This commit is contained in:
Luiz Capitulino 2011-10-20 17:01:33 -02:00
parent 2b54aa879e
commit d1f29646f2
7 changed files with 199 additions and 95 deletions

43
hmp.c
View File

@ -306,6 +306,49 @@ out:
qapi_free_VncInfo(info);
}
void hmp_info_spice(Monitor *mon)
{
SpiceChannelList *chan;
SpiceInfo *info;
info = qmp_query_spice(NULL);
if (!info->enabled) {
monitor_printf(mon, "Server: disabled\n");
goto out;
}
monitor_printf(mon, "Server:\n");
if (info->has_port) {
monitor_printf(mon, " address: %s:%" PRId64 "\n",
info->host, info->port);
}
if (info->has_tls_port) {
monitor_printf(mon, " address: %s:%" PRId64 " [tls]\n",
info->host, info->tls_port);
}
monitor_printf(mon, " auth: %s\n", info->auth);
monitor_printf(mon, " compiled: %s\n", info->compiled_version);
if (!info->has_channels || info->channels == NULL) {
monitor_printf(mon, "Channels: none\n");
} else {
for (chan = info->channels; chan; chan = chan->next) {
monitor_printf(mon, "Channel:\n");
monitor_printf(mon, " address: %s:%s%s\n",
chan->value->host, chan->value->port,
chan->value->tls ? " [tls]" : "");
monitor_printf(mon, " session: %" PRId64 "\n",
chan->value->connection_id);
monitor_printf(mon, " channel: %" PRId64 ":%" PRId64 "\n",
chan->value->channel_type, chan->value->channel_id);
}
}
out:
qapi_free_SpiceInfo(info);
}
void hmp_quit(Monitor *mon, const QDict *qdict)
{
monitor_suspend(mon);

1
hmp.h
View File

@ -29,6 +29,7 @@ void hmp_info_cpus(Monitor *mon);
void hmp_info_block(Monitor *mon);
void hmp_info_blockstats(Monitor *mon);
void hmp_info_vnc(Monitor *mon);
void hmp_info_spice(Monitor *mon);
void hmp_quit(Monitor *mon, const QDict *qdict);
void hmp_stop(Monitor *mon, const QDict *qdict);
void hmp_system_reset(Monitor *mon, const QDict *qdict);

View File

@ -2857,8 +2857,7 @@ static const mon_cmd_t info_cmds[] = {
.args_type = "",
.params = "",
.help = "show the spice server status",
.user_print = do_info_spice_print,
.mhandler.info_new = do_info_spice,
.mhandler.info = hmp_info_spice,
},
#endif
{
@ -2965,16 +2964,6 @@ static const mon_cmd_t qmp_query_cmds[] = {
.user_print = do_pci_info_print,
.mhandler.info_new = do_pci_info,
},
#if defined(CONFIG_SPICE)
{
.name = "spice",
.args_type = "",
.params = "",
.help = "show the spice server status",
.user_print = do_info_spice_print,
.mhandler.info_new = do_info_spice,
},
#endif
{
.name = "balloon",
.args_type = "",

View File

@ -584,6 +584,80 @@
##
{ 'command': 'query-vnc', 'returns': 'VncInfo' }
##
# @SpiceChannel
#
# Information about a SPICE client channel.
#
# @host: The host name of the client. QEMU tries to resolve this to a DNS name
# when possible.
#
# @family: 'ipv6' if the client is connected via IPv6 and TCP
# 'ipv4' if the client is connected via IPv4 and TCP
# 'unix' if the client is connected via a unix domain socket
# 'unknown' otherwise
#
# @port: The client's port number.
#
# @connection-id: SPICE connection id number. All channels with the same id
# belong to the same SPICE session.
#
# @connection-type: SPICE channel type number. "1" is the main control channel,
# filter for this one if you want track spice sessions only
#
# @channel-id: SPICE channel ID number. Usually "0", might be different needed
# when multiple channels of the same type exist, such as multiple
# display channels in a multihead setup
#
# @tls: true if the channel is encrypted, false otherwise.
#
# Since: 0.14.0
##
{ 'type': 'SpiceChannel',
'data': {'host': 'str', 'family': 'str', 'port': 'str',
'connection-id': 'int', 'channel-type': 'int', 'channel-id': 'int',
'tls': 'bool'} }
##
# @SpiceInfo
#
# Information about the SPICE session.
#
# @enabled: true if the SPICE server is enabled, false otherwise
#
# @host: #optional The hostname the SPICE server is bound to. This depends on
# the name resolution on the host and may be an IP address.
#
# @port: #optional The SPICE server's port number.
#
# @compiled-version: #optional SPICE server version.
#
# @tls-port: #optional The SPICE server's TLS port number.
#
# @auth: #optional the current authentication type used by the server
# 'none' if no authentication is being used
# 'spice' (TODO: describe)
#
# @channels: a list of @SpiceChannel for each active spice channel
#
# Since: 0.14.0
##
{ 'type': 'SpiceInfo',
'data': {'enabled': 'bool', '*host': 'str', '*port': 'int',
'*tls-port': 'int', '*auth': 'str', '*compiled-version': 'str',
'*channels': ['SpiceChannel']} }
##
# @query-spice
#
# Returns information about the current SPICE server
#
# Returns: @SpiceInfo
#
# Since: 0.14.0
##
{ 'command': 'query-spice', 'returns': 'SpiceInfo' }
##
# @quit:
#

View File

@ -1817,6 +1817,14 @@ Example:
EQMP
#if defined(CONFIG_SPICE)
{
.name = "query-spice",
.args_type = "",
.mhandler.cmd_new = qmp_marshal_input_query_spice,
},
#endif
SQMP
query-name
----------

12
qmp.c
View File

@ -105,3 +105,15 @@ VncInfo *qmp_query_vnc(Error **errp)
return NULL;
};
#endif
#ifndef CONFIG_SPICE
/* If SPICE support is enabled, the "true" query-spice command is
defined in the SPICE subsystem. Also note that we use a small
trick to maintain query-spice's original behavior, which is not
to be available in the namespace if SPICE is not compiled in */
SpiceInfo *qmp_query_spice(Error **errp)
{
error_set(errp, QERR_COMMAND_NOT_FOUND, "query-spice");
return NULL;
};
#endif

View File

@ -27,6 +27,7 @@
#include "qemu-queue.h"
#include "qemu-x509.h"
#include "qemu_socket.h"
#include "qmp-commands.h"
#include "qint.h"
#include "qbool.h"
#include "qstring.h"
@ -194,22 +195,6 @@ static void add_channel_info(QDict *dict, SpiceChannelEventInfo *info)
qdict_put(dict, "tls", qbool_from_int(tls));
}
static QList *channel_list_get(void)
{
ChannelList *item;
QList *list;
QDict *dict;
list = qlist_new();
QTAILQ_FOREACH(item, &channel_list, link) {
dict = qdict_new();
add_addr_info(dict, &item->info->paddr, item->info->plen);
add_channel_info(dict, item->info);
qlist_append(list, dict);
}
return list;
}
static void channel_event(int event, SpiceChannelEventInfo *info)
{
static const int qevent[] = {
@ -351,98 +336,90 @@ static const char *wan_compression_names[] = {
/* functions for the rest of qemu */
static void info_spice_iter(QObject *obj, void *opaque)
static SpiceChannelList *qmp_query_spice_channels(void)
{
QDict *client;
Monitor *mon = opaque;
SpiceChannelList *cur_item = NULL, *head = NULL;
ChannelList *item;
client = qobject_to_qdict(obj);
monitor_printf(mon, "Channel:\n");
monitor_printf(mon, " address: %s:%s%s\n",
qdict_get_str(client, "host"),
qdict_get_str(client, "port"),
qdict_get_bool(client, "tls") ? " [tls]" : "");
monitor_printf(mon, " session: %" PRId64 "\n",
qdict_get_int(client, "connection-id"));
monitor_printf(mon, " channel: %d:%d\n",
(int)qdict_get_int(client, "channel-type"),
(int)qdict_get_int(client, "channel-id"));
QTAILQ_FOREACH(item, &channel_list, link) {
SpiceChannelList *chan;
char host[NI_MAXHOST], port[NI_MAXSERV];
chan = g_malloc0(sizeof(*chan));
chan->value = g_malloc0(sizeof(*chan->value));
getnameinfo(&item->info->paddr, item->info->plen,
host, sizeof(host), port, sizeof(port),
NI_NUMERICHOST | NI_NUMERICSERV);
chan->value->host = g_strdup(host);
chan->value->port = g_strdup(port);
chan->value->family = g_strdup(inet_strfamily(item->info->paddr.sa_family));
chan->value->connection_id = item->info->connection_id;
chan->value->channel_type = item->info->type;
chan->value->channel_id = item->info->id;
chan->value->tls = item->info->flags & SPICE_CHANNEL_EVENT_FLAG_TLS;
/* XXX: waiting for the qapi to support GSList */
if (!cur_item) {
head = cur_item = chan;
} else {
cur_item->next = chan;
cur_item = chan;
}
}
return head;
}
void do_info_spice_print(Monitor *mon, const QObject *data)
{
QDict *server;
QList *channels;
const char *host;
int port;
server = qobject_to_qdict(data);
if (qdict_get_bool(server, "enabled") == 0) {
monitor_printf(mon, "Server: disabled\n");
return;
}
monitor_printf(mon, "Server:\n");
host = qdict_get_str(server, "host");
port = qdict_get_try_int(server, "port", -1);
if (port != -1) {
monitor_printf(mon, " address: %s:%d\n", host, port);
}
port = qdict_get_try_int(server, "tls-port", -1);
if (port != -1) {
monitor_printf(mon, " address: %s:%d [tls]\n", host, port);
}
monitor_printf(mon, " auth: %s\n", qdict_get_str(server, "auth"));
monitor_printf(mon, " compiled: %s\n",
qdict_get_str(server, "compiled-version"));
channels = qdict_get_qlist(server, "channels");
if (qlist_empty(channels)) {
monitor_printf(mon, "Channels: none\n");
} else {
qlist_iter(channels, info_spice_iter, mon);
}
}
void do_info_spice(Monitor *mon, QObject **ret_data)
SpiceInfo *qmp_query_spice(Error **errp)
{
QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head);
QDict *server;
QList *clist;
const char *addr;
int port, tls_port;
const char *addr;
SpiceInfo *info;
char version_string[20]; /* 12 = |255.255.255\0| is the max */
info = g_malloc0(sizeof(*info));
if (!spice_server) {
*ret_data = qobject_from_jsonf("{ 'enabled': false }");
return;
info->enabled = false;
return info;
}
info->enabled = true;
addr = qemu_opt_get(opts, "addr");
port = qemu_opt_get_number(opts, "port", 0);
tls_port = qemu_opt_get_number(opts, "tls-port", 0);
clist = channel_list_get();
server = qdict_new();
qdict_put(server, "enabled", qbool_from_int(true));
qdict_put(server, "auth", qstring_from_str(auth));
qdict_put(server, "host", qstring_from_str(addr ? addr : "0.0.0.0"));
info->has_auth = true;
info->auth = g_strdup(auth);
info->has_host = true;
info->host = g_strdup(addr ? addr : "0.0.0.0");
info->has_compiled_version = true;
snprintf(version_string, sizeof(version_string), "%d.%d.%d",
(SPICE_SERVER_VERSION & 0xff0000) >> 16,
(SPICE_SERVER_VERSION & 0xff00) >> 8,
SPICE_SERVER_VERSION & 0xff);
qdict_put(server, "compiled-version", qstring_from_str(version_string));
info->compiled_version = g_strdup(version_string);
if (port) {
qdict_put(server, "port", qint_from_int(port));
info->has_port = true;
info->port = port;
}
if (tls_port) {
qdict_put(server, "tls-port", qint_from_int(tls_port));
}
if (clist) {
qdict_put(server, "channels", clist);
info->has_tls_port = true;
info->tls_port = tls_port;
}
*ret_data = QOBJECT(server);
/* for compatibility with the original command */
info->has_channels = true;
info->channels = qmp_query_spice_channels();
return info;
}
static void migration_state_notifier(Notifier *notifier, void *data)