On Wed, 2011-09-21 at 13:59 +0100, Anthony PERARD wrote:
> QMP stands for QEMU Monitor Protocol and it is used to query information
> from QEMU or to control QEMU.
>
> This implementation will ask QEMU the list of chardevice and store the
> path to serial ports in xenstored. So we will be able to use xl console
> with QEMU upstream.
>
> In order to connect to the QMP server, a socket file is created in
> /var/run/xen/qmp-libxl-$(domid).
>
> Signed-off-by: Anthony PERARD <anthony.perard@xxxxxxxxxx>
Again I didn't fully review but I remember being happy with it lasttime
so:
Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
> ---
> tools/libxl/Makefile | 2 +-
> tools/libxl/libxl.c | 2 +
> tools/libxl/libxl_create.c | 4 +
> tools/libxl/libxl_dm.c | 10 +
> tools/libxl/libxl_internal.h | 19 ++
> tools/libxl/libxl_qmp.c | 587
> ++++++++++++++++++++++++++++++++++++++++++
> 6 files changed, 623 insertions(+), 1 deletions(-)
> create mode 100644 tools/libxl/libxl_qmp.c
>
> diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
> index e50874e..f10c7e8 100644
> --- a/tools/libxl/Makefile
> +++ b/tools/libxl/Makefile
> @@ -37,7 +37,7 @@ LIBXL_LIBS += -lyajl
> LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \
> libxl_dom.o libxl_exec.o libxl_xshelp.o
> libxl_device.o \
> libxl_internal.o libxl_utils.o libxl_uuid.o
> libxl_json.o \
> - $(LIBXL_OBJS-y)
> + libxl_qmp.o $(LIBXL_OBJS-y)
> LIBXL_OBJS += _libxl_types.o libxl_flask.o _libxl_types_internal.o
>
> $(LIBXL_OBJS): CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest)
> $(CFLAGS_libxenstore) $(CFLAGS_libblktapctl)
> diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
> index 426058f..fbd522d 100644
> --- a/tools/libxl/libxl.c
> +++ b/tools/libxl/libxl.c
> @@ -762,6 +762,8 @@ int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid,
> int force)
> if (dm_present) {
> if (libxl__destroy_device_model(&gc, domid) < 0)
> LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "libxl__destroy_device_model
> failed for %d", domid);
> +
> + libxl__qmp_cleanup(&gc, domid);
> }
> if (libxl__devices_destroy(&gc, domid, force) < 0)
> LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "libxl_destroy_devices failed for
> %d", domid);
> diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
> index ce76729..c97819a 100644
> --- a/tools/libxl/libxl_create.c
> +++ b/tools/libxl/libxl_create.c
> @@ -573,6 +573,10 @@ static int do_domain_create(libxl__gc *gc,
> libxl_domain_config *d_config,
> }
>
> if (dm_starting) {
> + if (dm_info->device_model_version
> + == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
> + libxl__qmp_initializations(ctx, domid);
> + }
> ret = libxl__confirm_device_model_startup(gc, dm_starting);
> if (ret < 0) {
> LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
> diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
> index e854a50..ef09079 100644
> --- a/tools/libxl/libxl_dm.c
> +++ b/tools/libxl/libxl_dm.c
> @@ -248,6 +248,16 @@ static char **
> libxl__build_device_model_args_new(libxl__gc *gc,
> flexarray_vappend(dm_args, dm,
> "-xen-domid", libxl__sprintf(gc, "%d", info->domid),
> NULL);
>
> + flexarray_append(dm_args, "-chardev");
> + flexarray_append(dm_args,
> + libxl__sprintf(gc, "socket,id=libxl-cmd,"
> + "path=%s/qmp-libxl-%d,server,nowait",
> + libxl_run_dir_path(),
> + info->domid));
> +
> + flexarray_append(dm_args, "-mon");
> + flexarray_append(dm_args, "chardev=libxl-cmd,mode=control");
> +
> if (info->type == LIBXL_DOMAIN_TYPE_PV) {
> flexarray_append(dm_args, "-xen-attach");
> }
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index f495e86..2ea1582 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -387,6 +387,25 @@ _hidden int libxl__e820_alloc(libxl_ctx *ctx, uint32_t
> domid, libxl_domain_confi
> #define STRINGIFY(x) #x
> #define TOSTRING(x) STRINGIFY(x)
>
> +/* from libxl_qmp */
> +typedef struct libxl__qmp_handler libxl__qmp_handler;
> +
> +/* Initialise and connect to the QMP socket.
> + * Return an handler or NULL if there is an error
> + */
> +_hidden libxl__qmp_handler *libxl__qmp_initialize(libxl_ctx *ctx,
> + uint32_t domid);
> +/* ask to QEMU the serial port information and store it in xenstore. */
> +_hidden int libxl__qmp_query_serial(libxl__qmp_handler *qmp);
> +/* close and free the QMP handler */
> +_hidden void libxl__qmp_close(libxl__qmp_handler *qmp);
> +/* remove the socket file, if the file has already been removed,
> + * nothing happen */
> +_hidden void libxl__qmp_cleanup(libxl__gc *gc, uint32_t domid);
> +
> +/* this helper calls qmp_initialize, query_serial and qmp_close */
> +_hidden int libxl__qmp_initializations(libxl_ctx *ctx, uint32_t domid);
> +
> /* from libxl_json */
> #include <yajl/yajl_gen.h>
>
> diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
> new file mode 100644
> index 0000000..6e8ecea
> --- /dev/null
> +++ b/tools/libxl/libxl_qmp.c
> @@ -0,0 +1,587 @@
> +/*
> + * Copyright (C) 2011 Citrix Ltd.
> + * Author Anthony PERARD <anthony.perard@xxxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU Lesser General Public License as published
> + * by the Free Software Foundation; version 2.1 only. with the special
> + * exception on linking described in file LICENSE.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU Lesser General Public License for more details.
> + */
> +
> +/*
> + * This file implement a client for QMP (QEMU Monitor Protocol). For the
> + * Specification, see in the QEMU repository.
> + */
> +
> +#include <unistd.h>
> +#include <sys/un.h>
> +#include <sys/queue.h>
> +
> +#include <yajl/yajl_gen.h>
> +
> +#include "libxl_internal.h"
> +
> +/* #define DEBUG_RECEIVED */
> +
> +#ifdef DEBUG_RECEIVED
> +# define DEBUG_REPORT_RECEIVED(buf, len) \
> + LIBXL__LOG(qmp->ctx, LIBXL__LOG_DEBUG, "received: '%.*s'", len, buf)
> +#else
> +# define DEBUG_REPORT_RECEIVED(buf, len) ((void)0)
> +#endif
> +
> +/*
> + * QMP types & constant
> + */
> +
> +#define QMP_RECEIVE_BUFFER_SIZE 4096
> +
> +typedef int (*qmp_callback_t)(libxl__qmp_handler *qmp,
> + const libxl__json_object *tree);
> +
> +typedef struct callback_id_pair {
> + int id;
> + qmp_callback_t callback;
> + SIMPLEQ_ENTRY(callback_id_pair) next;
> +} callback_id_pair;
> +
> +struct libxl__qmp_handler {
> + struct sockaddr_un addr;
> + int qmp_fd;
> + bool connected;
> + time_t timeout;
> + /* wait_for_id will be used by the synchronous send function */
> + int wait_for_id;
> +
> + char buffer[QMP_RECEIVE_BUFFER_SIZE];
> + libxl__yajl_ctx *yajl_ctx;
> +
> + libxl_ctx *ctx;
> + uint32_t domid;
> +
> + int last_id_used;
> + SIMPLEQ_HEAD(callback_list, callback_id_pair) callback_list;
> +};
> +
> +static int qmp_send(libxl__qmp_handler *qmp,
> + const char *cmd, qmp_callback_t callback);
> +
> +static const int QMP_SOCKET_CONNECT_TIMEOUT = 5;
> +
> +/*
> + * QMP callbacks functions
> + */
> +
> +static int store_serial_port_info(libxl__qmp_handler *qmp,
> + const char *chardev,
> + int port)
> +{
> + libxl__gc gc = LIBXL_INIT_GC(qmp->ctx);
> + char *path = NULL;
> + int ret = 0;
> +
> + if (!(chardev && strncmp("pty:", chardev, 4) == 0)) {
> + return -1;
> + }
> +
> + path = libxl__xs_get_dompath(&gc, qmp->domid);
> + path = libxl__sprintf(&gc, "%s/serial/%d/tty", path, port);
> +
> + ret = libxl__xs_write(&gc, XBT_NULL, path, "%s", chardev + 4);
> +
> + libxl__free_all(&gc);
> + return ret;
> +}
> +
> +static int register_serials_chardev_callback(libxl__qmp_handler *qmp,
> + const libxl__json_object *o)
> +{
> + const libxl__json_object *obj = NULL;
> + const libxl__json_object *label = NULL;
> + const char *s = NULL;
> + int i = 0;
> + const char *chardev = NULL;
> + int ret = 0;
> +
> + for (i = 0; (obj = libxl__json_array_get(o, i)); i++) {
> + if (!libxl__json_object_is_map(obj))
> + continue;
> + label = libxl__json_map_get("label", obj, JSON_STRING);
> + s = libxl__json_object_get_string(label);
> +
> + if (s && strncmp("serial", s, strlen("serial")) == 0) {
> + const libxl__json_object *filename = NULL;
> + char *endptr = NULL;
> + int port_number;
> +
> + filename = libxl__json_map_get("filename", obj, JSON_STRING);
> + chardev = libxl__json_object_get_string(filename);
> +
> + s += strlen("serial");
> + port_number = strtol(s, &endptr, 10);
> + if (*s == 0 || *endptr != 0) {
> + LIBXL__LOG(qmp->ctx, LIBXL__LOG_ERROR,
> + "Invalid serial port number: %s", s);
> + return -1;
> + }
> + ret = store_serial_port_info(qmp, chardev, port_number);
> + if (ret) {
> + LIBXL__LOG_ERRNO(qmp->ctx, LIBXL__LOG_ERROR,
> + "Failed to store serial port information"
> + " in xenstore");
> + return ret;
> + }
> + }
> + };
> +
> + return ret;
> +}
> +
> +static int qmp_capabilities_callback(libxl__qmp_handler *qmp,
> + const libxl__json_object *o)
> +{
> + qmp->connected = true;
> +
> + return 0;
> +}
> +
> +/*
> + * QMP commands
> + */
> +
> +static int enable_qmp_capabilities(libxl__qmp_handler *qmp)
> +{
> + return qmp_send(qmp, "qmp_capabilities", qmp_capabilities_callback);
> +}
> +
> +/*
> + * Helpers
> + */
> +
> +static libxl__qmp_message_type qmp_response_type(libxl__qmp_handler *qmp,
> + const libxl__json_object *o)
> +{
> + libxl__qmp_message_type type;
> + libxl__json_map_node *node = NULL;
> + int i = 0;
> +
> + for (i = 0; (node = libxl__json_map_node_get(o, i)); i++) {
> + if (libxl__qmp_message_type_from_string(node->map_key, &type) == 0)
> + return type;
> + }
> +
> + return LIBXL__QMP_MESSAGE_TYPE_INVALID;
> +}
> +
> +static callback_id_pair *qmp_get_callback_from_id(libxl__qmp_handler *qmp,
> + const libxl__json_object
> *o)
> +{
> + const libxl__json_object *id_object = libxl__json_map_get("id", o,
> + JSON_INTEGER);
> + int id = -1;
> + callback_id_pair *pp = NULL;
> +
> + if (id_object) {
> + id = libxl__json_object_get_integer(id_object);
> +
> + SIMPLEQ_FOREACH(pp, &qmp->callback_list, next) {
> + if (pp->id == id) {
> + return pp;
> + }
> + }
> + }
> + return NULL;
> +}
> +
> +static void qmp_handle_error_response(libxl__qmp_handler *qmp,
> + const libxl__json_object *resp)
> +{
> + callback_id_pair *pp = qmp_get_callback_from_id(qmp, resp);
> +
> + resp = libxl__json_map_get("error", resp, JSON_MAP);
> + resp = libxl__json_map_get("desc", resp, JSON_STRING);
> +
> + if (pp) {
> + pp->callback(qmp, NULL);
> + if (pp->id == qmp->wait_for_id) {
> + /* tell that the id have been processed */
> + qmp->wait_for_id = 0;
> + }
> + SIMPLEQ_REMOVE(&qmp->callback_list, pp, callback_id_pair, next);
> + free(pp);
> + }
> +
> + LIBXL__LOG(qmp->ctx, LIBXL__LOG_ERROR,
> + "received an error message from QMP server: %s",
> + libxl__json_object_get_string(resp));
> +}
> +
> +static int qmp_handle_response(libxl__qmp_handler *qmp,
> + const libxl__json_object *resp)
> +{
> + libxl__qmp_message_type type = LIBXL__QMP_MESSAGE_TYPE_INVALID;
> +
> + type = qmp_response_type(qmp, resp);
> + LIBXL__LOG(qmp->ctx, LIBXL__LOG_DEBUG,
> + "message type: %s", libxl__qmp_message_type_to_string(type));
> +
> + switch (type) {
> + case LIBXL__QMP_MESSAGE_TYPE_QMP:
> + /* On the greeting message from the server, enable QMP capabilities
> */
> + enable_qmp_capabilities(qmp);
> + break;
> + case LIBXL__QMP_MESSAGE_TYPE_RETURN: {
> + callback_id_pair *pp = qmp_get_callback_from_id(qmp, resp);
> +
> + if (pp) {
> + pp->callback(qmp,
> + libxl__json_map_get("return", resp, JSON_ANY));
> + if (pp->id == qmp->wait_for_id) {
> + /* tell that the id have been processed */
> + qmp->wait_for_id = 0;
> + }
> + SIMPLEQ_REMOVE(&qmp->callback_list, pp, callback_id_pair, next);
> + free(pp);
> + }
> + break;
> + }
> + case LIBXL__QMP_MESSAGE_TYPE_ERROR:
> + qmp_handle_error_response(qmp, resp);
> + break;
> + case LIBXL__QMP_MESSAGE_TYPE_EVENT:
> + break;
> + case LIBXL__QMP_MESSAGE_TYPE_INVALID:
> + return -1;
> + }
> + return 0;
> +}
> +
> +/*
> + * Handler functions
> + */
> +
> +static libxl__qmp_handler *qmp_init_handler(libxl_ctx *ctx, uint32_t domid)
> +{
> + libxl__qmp_handler *qmp = NULL;
> +
> + qmp = calloc(1, sizeof (libxl__qmp_handler));
> + if (qmp == NULL) {
> + LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
> + "Failed to allocate qmp_handler");
> + return NULL;
> + }
> + qmp->ctx = ctx;
> + qmp->domid = domid;
> + qmp->timeout = 5;
> +
> + SIMPLEQ_INIT(&qmp->callback_list);
> +
> + return qmp;
> +}
> +
> +static int qmp_open(libxl__qmp_handler *qmp, const char *qmp_socket_path,
> + int timeout)
> +{
> + int ret;
> + int i = 0;
> +
> + qmp->qmp_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
> + if (qmp->qmp_fd < 0) {
> + return -1;
> + }
> +
> + memset(&qmp->addr, 0, sizeof (&qmp->addr));
> + qmp->addr.sun_family = AF_UNIX;
> + strncpy(qmp->addr.sun_path, qmp_socket_path,
> + sizeof (qmp->addr.sun_path));
> +
> + do {
> + ret = connect(qmp->qmp_fd, (struct sockaddr *) &qmp->addr,
> + sizeof (qmp->addr));
> + if (ret == 0)
> + break;
> + if (errno == ENOENT || errno == ECONNREFUSED) {
> + /* ENOENT : Socket may not have shown up yet
> + * ECONNREFUSED : Leftover socket hasn't been removed yet */
> + continue;
> + }
> + return -1;
> + } while ((++i / 5 <= timeout) && (usleep(200 * 1000) <= 0));
> +
> + return ret;
> +}
> +
> +static void qmp_close(libxl__qmp_handler *qmp)
> +{
> + callback_id_pair *pp = NULL;
> + callback_id_pair *tmp = NULL;
> +
> + close(qmp->qmp_fd);
> + SIMPLEQ_FOREACH(pp, &qmp->callback_list, next) {
> + if (tmp)
> + free(tmp);
> + tmp = pp;
> + }
> + if (tmp)
> + free(tmp);
> +}
> +
> +static int qmp_next(libxl__gc *gc, libxl__qmp_handler *qmp)
> +{
> + ssize_t rd;
> + char *s = NULL;
> + char *s_end = NULL;
> +
> + char *incomplete = NULL;
> + size_t incomplete_size = 0;
> +
> + do {
> + fd_set rfds;
> + int ret = 0;
> + struct timeval timeout = {
> + .tv_sec = qmp->timeout,
> + .tv_usec = 0,
> + };
> +
> + FD_ZERO(&rfds);
> + FD_SET(qmp->qmp_fd, &rfds);
> +
> + ret = select(qmp->qmp_fd + 1, &rfds, NULL, NULL, &timeout);
> + if (ret == 0) {
> + LIBXL__LOG(qmp->ctx, LIBXL__LOG_ERROR, "timeout");
> + return -1;
> + } else if (ret < 0) {
> + LIBXL__LOG_ERRNO(qmp->ctx, LIBXL__LOG_ERROR, "Select error");
> + return -1;
> + }
> +
> + rd = read(qmp->qmp_fd, qmp->buffer, QMP_RECEIVE_BUFFER_SIZE);
> + if (rd == 0) {
> + continue;
> + } else if (rd < 0) {
> + LIBXL__LOG_ERRNO(qmp->ctx, LIBXL__LOG_ERROR, "Socket read
> error");
> + return rd;
> + }
> +
> + DEBUG_REPORT_RECEIVED(qmp->buffer, rd);
> +
> + do {
> + char *end = NULL;
> + if (incomplete) {
> + size_t current_pos = s - incomplete;
> + incomplete_size += rd;
> + incomplete = libxl__realloc(gc, incomplete,
> + incomplete_size + 1);
> + incomplete = strncat(incomplete, qmp->buffer, rd);
> + s = incomplete + current_pos;
> + s_end = incomplete + incomplete_size;
> + } else {
> + incomplete = libxl__strndup(gc, qmp->buffer, rd);
> + incomplete_size = rd;
> + s = incomplete;
> + s_end = s + rd;
> + }
> +
> + end = strstr(s, "\r\n");
> + if (end) {
> + libxl__json_object *o = NULL;
> +
> + *end = '\0';
> +
> + o = libxl__json_parse(gc, s);
> + s = end + 2;
> +
> + if (o) {
> + qmp_handle_response(qmp, o);
> + libxl__json_object_free(gc, o);
> + } else {
> + LIBXL__LOG(qmp->ctx, LIBXL__LOG_ERROR,
> + "Parse error of : %s\n", s);
> + return -1;
> + }
> + } else {
> + break;
> + }
> + } while (s < s_end);
> + } while (s < s_end);
> +
> + return 1;
> +}
> +
> +static int qmp_send(libxl__qmp_handler *qmp,
> + const char *cmd, qmp_callback_t callback)
> +{
> + yajl_gen_config conf = { 0, NULL };
> + const unsigned char *buf;
> + unsigned int len = 0;
> + yajl_gen_status s;
> + yajl_gen hand;
> +
> + hand = yajl_gen_alloc(&conf, NULL);
> + if (!hand) {
> + return -1;
> + }
> +
> + yajl_gen_map_open(hand);
> + libxl__yajl_gen_asciiz(hand, "execute");
> + libxl__yajl_gen_asciiz(hand, cmd);
> + libxl__yajl_gen_asciiz(hand, "id");
> + yajl_gen_integer(hand, ++qmp->last_id_used);
> + yajl_gen_map_close(hand);
> +
> + s = yajl_gen_get_buf(hand, &buf, &len);
> +
> + if (s) {
> + LIBXL__LOG(qmp->ctx, LIBXL__LOG_ERROR,
> + "Failed to generate a qmp command");
> + return -1;
> + }
> +
> + if (callback) {
> + callback_id_pair *elm = malloc(sizeof (callback_id_pair));
> + if (elm == NULL) {
> + LIBXL__LOG_ERRNO(qmp->ctx, LIBXL__LOG_ERROR,
> + "Failed to allocate a QMP callback");
> + yajl_gen_free(hand);
> + return -1;
> + }
> + elm->id = qmp->last_id_used;
> + elm->callback = callback;
> + SIMPLEQ_INSERT_TAIL(&qmp->callback_list, elm, next);
> + }
> +
> + LIBXL__LOG(qmp->ctx, LIBXL__LOG_DEBUG, "next qmp command: '%s'", buf);
> +
> + if (libxl_write_exactly(qmp->ctx, qmp->qmp_fd, buf, len,
> + "QMP command", "QMP socket"))
> + goto error;
> + if (libxl_write_exactly(qmp->ctx, qmp->qmp_fd, "\r\n", 2,
> + "CRLF", "QMP socket"))
> + goto error;
> +
> + yajl_gen_free(hand);
> +
> + return qmp->last_id_used;
> +
> +error:
> + yajl_gen_free(hand);
> + return -1;
> +}
> +
> +static int qmp_synchronous_send(libxl__qmp_handler *qmp, const char *cmd,
> + qmp_callback_t callback, int ask_timeout)
> +{
> + int id = 0;
> + int ret = 0;
> + libxl__gc gc = LIBXL_INIT_GC(qmp->ctx);
> +
> + id = qmp_send(qmp, cmd, callback);
> + if (id <= 0) {
> + return -1;
> + }
> + qmp->wait_for_id = id;
> +
> + while (qmp->wait_for_id == id) {
> + if ((ret = qmp_next(&gc, qmp)) < 0) {
> + return ret;
> + }
> + }
> +
> + libxl__free_all(&gc);
> +
> + return 0;
> +}
> +
> +static void qmp_free_handler(libxl__qmp_handler *qmp)
> +{
> + free(qmp);
> +}
> +
> +/*
> + * API
> + */
> +
> +libxl__qmp_handler *libxl__qmp_initialize(libxl_ctx *ctx, uint32_t domid)
> +{
> + int ret = 0;
> + libxl__qmp_handler *qmp = NULL;
> + char *qmp_socket;
> + libxl__gc gc = LIBXL_INIT_GC(ctx);
> +
> + qmp = qmp_init_handler(ctx, domid);
> +
> + qmp_socket = libxl__sprintf(&gc, "%s/qmp-libxl-%d",
> + libxl_run_dir_path(), domid);
> + if ((ret = qmp_open(qmp, qmp_socket, QMP_SOCKET_CONNECT_TIMEOUT)) < 0) {
> + LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Connection error");
> + libxl__free_all(&gc);
> + qmp_free_handler(qmp);
> + return NULL;
> + }
> +
> + LIBXL__LOG(qmp->ctx, LIBXL__LOG_DEBUG, "connected to %s", qmp_socket);
> +
> + /* Wait for the response to qmp_capabilities */
> + while (!qmp->connected) {
> + if ((ret = qmp_next(&gc, qmp)) < 0) {
> + break;
> + }
> + }
> +
> + libxl__free_all(&gc);
> + if (!qmp->connected) {
> + LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Failed to connect to QMP");
> + libxl__qmp_close(qmp);
> + return NULL;
> + }
> + return qmp;
> +}
> +
> +void libxl__qmp_close(libxl__qmp_handler *qmp)
> +{
> + if (!qmp)
> + return;
> + qmp_close(qmp);
> + qmp_free_handler(qmp);
> +}
> +
> +void libxl__qmp_cleanup(libxl__gc *gc, uint32_t domid)
> +{
> + libxl_ctx *ctx = libxl__gc_owner(gc);
> + char *qmp_socket;
> +
> + qmp_socket = libxl__sprintf(gc, "%s/qmp-libxl-%d",
> + libxl_run_dir_path(), domid);
> + if (unlink(qmp_socket) == -1) {
> + if (errno != ENOENT) {
> + LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
> + "Failed to remove QMP socket file %s",
> + qmp_socket);
> + }
> + }
> +}
> +
> +int libxl__qmp_query_serial(libxl__qmp_handler *qmp)
> +{
> + return qmp_synchronous_send(qmp, "query-chardev",
> + register_serials_chardev_callback,
> + qmp->timeout);
> +}
> +
> +int libxl__qmp_initializations(libxl_ctx *ctx, uint32_t domid)
> +{
> + libxl__qmp_handler *qmp = NULL;
> + int ret = 0;
> +
> + qmp = libxl__qmp_initialize(ctx, domid);
> + if (!qmp)
> + return -1;
> + ret = libxl__qmp_query_serial(qmp);
> + libxl__qmp_close(qmp);
> + return ret;
> +}
> --
> Anthony PERARD
>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|