From fffbde4e7b49d4c49f9f2d739572e51833c39d90 Mon Sep 17 00:00:00 2001
From: Thilo Boehm <tboehm@linux.vnet.ibm.com>
Date: Wed, 11 Sep 2013 16:45:37 +0200
Subject: [PATCH 17/60] libxkutil: Console Support
Added data types for the representation of console devices and their
source type specific properties.
Further, implemented libvirt XML parsing and generation of console
device XML.
Signed-off-by: Thilo Boehm <tboehm@linux.vnet.ibm.com>
Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
Reviewed-by: Boris Fiuczynski <fiuczy@linux.vnet.ibm.com>
Signed-off-by: John Ferlan <jferlan@redhat.com>
---
libxkutil/device_parsing.c | 314 +++++++++++++++++++++++++++++++++++++++++++--
libxkutil/device_parsing.h | 43 ++++++-
libxkutil/xmlgen.c | 191 ++++++++++++++++++++++++++-
src/svpc_types.h | 5 +-
4 files changed, 541 insertions(+), 12 deletions(-)
diff --git a/libxkutil/device_parsing.c b/libxkutil/device_parsing.c
index f55061e..55c8d57 100644
--- a/libxkutil/device_parsing.c
+++ b/libxkutil/device_parsing.c
@@ -1,5 +1,5 @@
/*
- * Copyright IBM Corp. 2007
+ * Copyright IBM Corp. 2007, 2013
*
* Authors:
* Dan Smith <danms@us.ibm.com>
@@ -41,6 +41,11 @@
#define NET_XPATH (xmlChar *)"/domain/devices/interface"
#define EMU_XPATH (xmlChar *)"/domain/devices/emulator"
#define MEM_XPATH (xmlChar *)"/domain/memory | /domain/currentMemory"
+#define CONSOLE_XPATH (xmlChar *)"/domain/devices/console"
+/*
+ * To be backward compatible, serial and console is
+ * still part of the graphics.
+ */
#define GRAPHICS_XPATH (xmlChar *)"/domain/devices/graphics | "\
"/domain/devices/console | /domain/devices/serial"
#define INPUT_XPATH (xmlChar *)"/domain/devices/input"
@@ -50,6 +55,11 @@
#define MAX(a,b) (((a)>(b))?(a):(b))
+#define DUP_FIELD(d, s, f) do { \
+ if ((s)->f != NULL) \
+ (d)->f = strdup((s)->f); \
+ } while (0);
+
/* Device parse function */
typedef int (*dev_parse_func_t)(xmlNode *, struct virt_device **);
@@ -135,6 +145,140 @@ static void cleanup_graphics_device(struct graphics_device *dev)
free(dev->type);
}
+static void cleanup_path_device(struct path_device *dev)
+{
+ if (dev == NULL)
+ return;
+
+ free(dev->path);
+
+}
+
+static void cleanup_unixsock_device(struct unixsock_device *dev)
+{
+ if (dev == NULL)
+ return;
+
+ free(dev->path);
+ free(dev->mode);
+
+}
+
+static void cleanup_tcp_device(struct tcp_device *dev)
+{
+ if (dev == NULL)
+ return;
+
+ free(dev->mode);
+ free(dev->protocol);
+ free(dev->host);
+ free(dev->service);
+
+}
+
+static void cleanup_udp_device(struct udp_device *dev)
+{
+ if (dev == NULL)
+ return;
+
+ free(dev->bind_host);
+ free(dev->bind_service);
+ free(dev->connect_host);
+ free(dev->connect_service);
+};
+
+static void cleanup_console_device(struct console_device *dev)
+{
+ if (dev == NULL)
+ return;
+
+ switch (dev->source_type)
+ {
+ case CIM_CHARDEV_SOURCE_TYPE_PTY:
+ cleanup_path_device(&dev->source_dev.pty);
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_DEV:
+ cleanup_path_device(&dev->source_dev.dev);
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_FILE:
+ cleanup_path_device(&dev->source_dev.file);
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_PIPE:
+ cleanup_path_device(&dev->source_dev.pipe);
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_UNIXSOCK:
+ cleanup_unixsock_device(&dev->source_dev.unixsock);
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_UDP:
+ cleanup_udp_device(&dev->source_dev.udp);
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_TCP:
+ cleanup_tcp_device(&dev->source_dev.tcp);
+ break;
+ default:
+ /* Nothing to do for :
+ CIM_CHARDEV_SOURCE_TYPE_STDIO
+ CIM_CHARDEV_SOURCE_TYPE_NULL
+ CIM_CHARDEV_SOURCE_TYPE_VC
+ CIM_CHARDEV_SOURCE_TYPE_SPICEVMC
+ */
+ break;
+ }
+
+ dev->source_type = 0;
+ free(dev->target_type);
+ memset(&dev->source_dev, 0, sizeof(dev->source_dev));
+};
+
+static void console_device_dup(struct console_device *t,
+ struct console_device *s)
+{
+ cleanup_console_device(t);
+
+ t->source_type = s->source_type;
+ DUP_FIELD(t, s, target_type);
+
+ switch (s->source_type)
+ {
+ case CIM_CHARDEV_SOURCE_TYPE_PTY:
+ DUP_FIELD(t, s, source_dev.pty.path);
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_DEV:
+ DUP_FIELD(t, s, source_dev.dev.path);
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_FILE:
+ DUP_FIELD(t, s, source_dev.file.path);
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_PIPE:
+ DUP_FIELD(t, s, source_dev.pipe.path);
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_UNIXSOCK:
+ DUP_FIELD(t, s, source_dev.unixsock.path);
+ DUP_FIELD(t, s, source_dev.unixsock.mode);
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_UDP:
+ DUP_FIELD(t, s, source_dev.udp.bind_host);
+ DUP_FIELD(t, s, source_dev.udp.bind_service);
+ DUP_FIELD(t, s, source_dev.udp.connect_host);
+ DUP_FIELD(t, s, source_dev.udp.connect_service);
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_TCP:
+ DUP_FIELD(t, s, source_dev.tcp.mode);
+ DUP_FIELD(t, s, source_dev.tcp.protocol);
+ DUP_FIELD(t, s, source_dev.tcp.host);
+ DUP_FIELD(t, s, source_dev.tcp.service);
+ break;
+ default:
+ /* Nothing to do for :
+ CIM_CHARDEV_SOURCE_TYPE_STDIO
+ CIM_CHARDEV_SOURCE_TYPE_NULL
+ CIM_CHARDEV_SOURCE_TYPE_VC
+ CIM_CHARDEV_SOURCE_TYPE_SPICEVMC
+ */
+ break;
+ }
+}
+
static void cleanup_input_device(struct input_device *dev)
{
if (dev == NULL)
@@ -159,6 +303,8 @@ void cleanup_virt_device(struct virt_device *dev)
cleanup_graphics_device(&dev->dev.graphics);
else if (dev->type == CIM_RES_TYPE_INPUT)
cleanup_input_device(&dev->dev.input);
+ else if (dev->type == CIM_RES_TYPE_CONSOLE)
+ cleanup_console_device(&dev->dev.console);
free(dev->id);
@@ -616,6 +762,138 @@ static char *get_attr_value_default(xmlNode *node, char *attrname,
return ret;
}
+static int parse_console_device(xmlNode *node, struct virt_device **vdevs)
+{
+ struct virt_device *vdev = NULL;
+ struct console_device *cdev = NULL;
+ char *source_type_str = NULL;
+ char *target_port_ID = NULL;
+ char *udp_source_mode = NULL;
+
+ xmlNode *child = NULL;
+
+ vdev = calloc(1, sizeof(*vdev));
+ if (vdev == NULL)
+ goto err;
+
+ cdev = &(vdev->dev.console);
+
+ source_type_str = get_attr_value(node, "type");
+ if (source_type_str == NULL)
+ goto err;
+ CU_DEBUG("console device type = %s", source_type_str ? : "NULL");
+
+ cdev->source_type = chardev_source_type_StrToID(source_type_str);
+ if (cdev->source_type == CIM_CHARDEV_SOURCE_TYPE_UNKNOWN)
+ goto err;
+
+ CU_DEBUG("console device type ID = %d", cdev->source_type);
+
+ for (child = node->children; child != NULL; child = child->next) {
+ if (XSTREQ(child->name, "target")) {
+ cdev->target_type = get_attr_value(child, "type");
+ CU_DEBUG("Console device target type = '%s'",
+ cdev->target_type ? : "NULL");
+ target_port_ID = get_attr_value(child, "port");
+ if (target_port_ID == NULL)
+ goto err;
+ }
+
+ if (XSTREQ(child->name, "source")) {
+ switch (cdev->source_type)
+ {
+ case CIM_CHARDEV_SOURCE_TYPE_PTY:
+ cdev->source_dev.pty.path =
+ get_attr_value(child, "path");
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_DEV:
+ cdev->source_dev.dev.path =
+ get_attr_value(child, "path");
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_FILE:
+ cdev->source_dev.file.path =
+ get_attr_value(child, "path");
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_PIPE:
+ cdev->source_dev.pipe.path =
+ get_attr_value(child, "path");
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_UNIXSOCK:
+ cdev->source_dev.unixsock.mode =
+ get_attr_value(child, "mode");
+ cdev->source_dev.unixsock.path =
+ get_attr_value(child, "path");
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_UDP:
+ udp_source_mode = get_attr_value(child, "mode");
+ if (udp_source_mode == NULL)
+ goto err;
+ if (STREQC(udp_source_mode, "bind")) {
+ cdev->source_dev.udp.bind_host =
+ get_attr_value(child, "host");
+ cdev->source_dev.udp.bind_service =
+ get_attr_value(child, "service");
+ } else if (STREQC(udp_source_mode, "connect")) {
+ cdev->source_dev.udp.connect_host =
+ get_attr_value(child, "host");
+ cdev->source_dev.udp.connect_service =
+ get_attr_value(child, "service");
+ } else {
+ CU_DEBUG("unknown udp mode: %s",
+ udp_source_mode ? : "NULL");
+ goto err;
+ }
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_TCP:
+ cdev->source_dev.tcp.mode =
+ get_attr_value(child, "mode");
+ cdev->source_dev.tcp.host =
+ get_attr_value(child, "host");
+ cdev->source_dev.tcp.service =
+ get_attr_value(child, "service");
+ break;
+
+ default:
+ /* Nothing to do for :
+ CIM_CHARDEV_SOURCE_TYPE_STDIO
+ CIM_CHARDEV_SOURCE_TYPE_NULL
+ CIM_CHARDEV_SOURCE_TYPE_VC
+ CIM_CHARDEV_SOURCE_TYPE_SPICEVMC
+ */
+ break;
+ }
+ }
+ if ((cdev->source_type == CIM_CHARDEV_SOURCE_TYPE_TCP)
+ && XSTREQ(child->name, "protocol")) {
+ cdev->source_dev.tcp.protocol =
+ get_attr_value(child, "type");
+ }
+ }
+
+ vdev->type = CIM_RES_TYPE_CONSOLE;
+
+ if (asprintf(&vdev->id, "charconsole:%s", target_port_ID) == -1) {
+ CU_DEBUG("Failed to create charconsole id string");
+ goto err;
+ }
+
+ *vdevs = vdev;
+ free(source_type_str);
+ free(target_port_ID);
+ free(udp_source_mode);
+
+ return 1;
+
+ err:
+ free(source_type_str);
+ free(target_port_ID);
+ free(udp_source_mode);
+ cleanup_console_device(cdev);
+ free(vdev);
+
+ return 0;
+}
+
static int parse_graphics_device(xmlNode *node, struct virt_device **vdevs)
{
struct virt_device *vdev = NULL;
@@ -667,8 +945,20 @@ static int parse_graphics_device(xmlNode *node, struct virt_device **vdevs)
child = child->next) {
if (XSTREQ(child->name, "source"))
gdev->dev.vnc.host = get_attr_value(child, "path");
- else if (XSTREQ(child->name, "target"))
- gdev->dev.vnc.port = get_attr_value(child, "port");
+ else if (XSTREQ(child->name, "target")) {
+ gdev->dev.vnc.port =
+ get_attr_value(child, "port");
+ /* The graphics pty console can only be a
+ virtio console. If 'type' is not set in the
+ xml, the default of libvirt is virtio.*/
+ char *t_type = get_attr_value(child, "type");
+ if (t_type != NULL && !STREQC(t_type, "virtio")) {
+ CU_DEBUG("Not a pty-virtio graphics console");
+ free(t_type);
+ goto err;
+ }
+ free(t_type);
+ }
}
}
else {
@@ -847,6 +1137,11 @@ static int parse_devices(const char *xml, struct virt_device **_list, int type)
func = &parse_graphics_device;
break;
+ case CIM_RES_TYPE_CONSOLE:
+ xpathstr = CONSOLE_XPATH;
+ func = &parse_console_device;
+ break;
+
case CIM_RES_TYPE_INPUT:
xpathstr = INPUT_XPATH;
func = &parse_input_device;
@@ -882,11 +1177,6 @@ static int parse_devices(const char *xml, struct virt_device **_list, int type)
return count;
}
-#define DUP_FIELD(d, s, f) do { \
- if ((s)->f != NULL) \
- (d)->f = strdup((s)->f); \
- } while (0);
-
struct virt_device *virt_device_dup(struct virt_device *_dev)
{
struct virt_device *dev;
@@ -945,8 +1235,10 @@ struct virt_device *virt_device_dup(struct virt_device *_dev)
} else if (dev->type == CIM_RES_TYPE_INPUT) {
DUP_FIELD(dev, _dev, dev.input.type);
DUP_FIELD(dev, _dev, dev.input.bus);
+ } else if (dev->type == CIM_RES_TYPE_CONSOLE) {
+ console_device_dup(&dev->dev.console,
+ &_dev->dev.console);
}
-
return dev;
}
@@ -1307,6 +1599,9 @@ int get_dominfo_from_xml(const char *xml, struct domain **dominfo)
(*dominfo)->dev_graphics_ct = parse_devices(xml,
&(*dominfo)->dev_graphics,
CIM_RES_TYPE_GRAPHICS);
+ (*dominfo)->dev_console_ct = parse_devices(xml,
+ &(*dominfo)->dev_console,
+ CIM_RES_TYPE_CONSOLE);
(*dominfo)->dev_input_ct = parse_devices(xml,
&(*dominfo)->dev_input,
CIM_RES_TYPE_INPUT);
@@ -1407,6 +1702,7 @@ void cleanup_dominfo(struct domain **dominfo)
cleanup_virt_devices(&dom->dev_vcpu, dom->dev_vcpu_ct);
cleanup_virt_devices(&dom->dev_graphics, dom->dev_graphics_ct);
cleanup_virt_devices(&dom->dev_input, dom->dev_input_ct);
+ cleanup_virt_devices(&dom->dev_console, dom->dev_console_ct);
free(dom);
diff --git a/libxkutil/device_parsing.h b/libxkutil/device_parsing.h
index 14e49b8..2803d6a 100644
--- a/libxkutil/device_parsing.h
+++ b/libxkutil/device_parsing.h
@@ -1,5 +1,5 @@
/*
- * Copyright IBM Corp. 2007
+ * Copyright IBM Corp. 2007, 2013
*
* Authors:
* Dan Smith <danms@us.ibm.com>
@@ -111,6 +111,43 @@ struct graphics_device {
} dev;
};
+struct path_device {
+ char *path;
+};
+
+struct unixsock_device {
+ char *path;
+ char *mode;
+};
+
+struct tcp_device {
+ char *mode;
+ char *protocol;
+ char *host;
+ char *service;
+};
+
+struct udp_device {
+ char *bind_host;
+ char *bind_service;
+ char *connect_host;
+ char *connect_service;
+};
+
+struct console_device {
+ uint16_t source_type;
+ union {
+ struct path_device file;
+ struct path_device pty;
+ struct path_device dev;
+ struct path_device pipe;
+ struct unixsock_device unixsock;
+ struct tcp_device tcp;
+ struct udp_device udp;
+ } source_dev;
+ char *target_type;
+};
+
struct input_device {
char *type;
char *bus;
@@ -125,6 +162,7 @@ struct virt_device {
struct vcpu_device vcpu;
struct emu_device emu;
struct graphics_device graphics;
+ struct console_device console;
struct input_device input;
} dev;
char *id;
@@ -182,6 +220,9 @@ struct domain {
struct virt_device *dev_graphics;
int dev_graphics_ct;
+ struct virt_device *dev_console;
+ int dev_console_ct;
+
struct virt_device *dev_emu;
struct virt_device *dev_input;
diff --git a/libxkutil/xmlgen.c b/libxkutil/xmlgen.c
index 2ca2341..45bfb04 100644
--- a/libxkutil/xmlgen.c
+++ b/libxkutil/xmlgen.c
@@ -1,5 +1,5 @@
/*
- * Copyright IBM Corp. 2007
+ * Copyright IBM Corp. 2007, 2013
*
* Authors:
* Dan Smith <danms@us.ibm.com>
@@ -42,6 +42,189 @@ typedef const char *(*devfn_t)(xmlNodePtr node, struct domain *dominfo);
typedef const char *(*poolfn_t)(xmlNodePtr node, struct virt_pool *pool);
typedef const char *(*resfn_t)(xmlNodePtr node, struct virt_pool_res *res);
+static int _count_graphics_console_definitions(struct domain *dominfo)
+{
+ int i;
+ int num = 0;
+
+ for (i = 0; i < dominfo->dev_graphics_ct; i++) {
+ struct virt_device *_dev = &dominfo->dev_graphics[i];
+ if (_dev->type == CIM_RES_TYPE_UNKNOWN)
+ continue;
+
+ struct graphics_device *dev = &_dev->dev.graphics;
+
+ if (STREQC(dev->type, "console")) {
+ num++;
+ }
+ }
+ CU_DEBUG("Found %d console defintions in graphics devices.",num);
+ return num;
+
+}
+
+static const char *console_xml(xmlNodePtr root, struct domain *dominfo)
+{
+ int i;
+ xmlNodePtr console;
+ xmlNodePtr tmp;
+ int num_graphics_consol_def = 0;
+ int num_suppressed_console_def = 0;
+
+ num_graphics_consol_def = _count_graphics_console_definitions(dominfo);
+
+ for (i = 0; i < dominfo->dev_console_ct; i++) {
+ struct virt_device *_dev = &dominfo->dev_console[i];
+ if (_dev->type == CIM_RES_TYPE_UNKNOWN)
+ continue;
+
+ struct console_device *cdev = &_dev->dev.console;
+
+ /* Due to backward compatibility, the graphics device handling
+ is still parsing consoles:
+ source = pty, target = virtio (which is the default target)
+ But the console device handling processes these kind of
+ consoles too. This would lead to a duplication of these
+ default consoles in the domain xml definition.
+ This code prevents the console handling of writing xml for
+ duplicate pty/virtio consoles which are written by the
+ graphics device handling. */
+ if (cdev->source_type == CIM_CHARDEV_SOURCE_TYPE_PTY &&
+ (cdev->target_type == NULL ||
+ STREQC(cdev->target_type, "virtio"))) {
+ if (num_suppressed_console_def <
+ num_graphics_consol_def) {
+ num_suppressed_console_def++;
+ continue;
+ }
+ }
+
+ console = xmlNewChild(root, NULL, BAD_CAST "console", NULL);
+ if (console == NULL)
+ return XML_ERROR;
+
+ xmlNewProp(console, BAD_CAST "type",
+ BAD_CAST
+ chardev_source_type_IDToStr(cdev->source_type));
+
+ switch (cdev->source_type) {
+ case CIM_CHARDEV_SOURCE_TYPE_PTY:
+ /* The path property is not mandatory */
+ if (cdev->source_dev.pty.path) {
+ tmp = xmlNewChild(console, NULL,
+ BAD_CAST "source", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "path",
+ BAD_CAST cdev->source_dev.pty.path);
+ }
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_DEV:
+ tmp = xmlNewChild(console, NULL,
+ BAD_CAST "source", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "path",
+ BAD_CAST cdev->source_dev.dev.path);
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_FILE:
+ tmp = xmlNewChild(console, NULL,
+ BAD_CAST "source", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "path",
+ BAD_CAST cdev->source_dev.file.path);
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_PIPE:
+ tmp = xmlNewChild(console, NULL,
+ BAD_CAST "source", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "path",
+ BAD_CAST cdev->source_dev.pipe.path);
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_UNIXSOCK:
+ tmp = xmlNewChild(console, NULL,
+ BAD_CAST "source", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "mode",
+ BAD_CAST cdev->source_dev.unixsock.mode);
+ xmlNewProp(tmp, BAD_CAST "path",
+ BAD_CAST cdev->source_dev.unixsock.path);
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_UDP:
+ tmp = xmlNewChild(console, NULL,
+ BAD_CAST "source", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "mode", BAD_CAST "bind");
+ xmlNewProp(tmp, BAD_CAST "host",
+ BAD_CAST cdev->source_dev.udp.bind_host);
+ /* The service property is not mandatory */
+ if (cdev->source_dev.udp.bind_service)
+ xmlNewProp(tmp, BAD_CAST "service",
+ BAD_CAST
+ cdev->source_dev.udp.bind_service);
+
+ tmp = xmlNewChild(console, NULL,
+ BAD_CAST "source", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "mode", BAD_CAST "connect");
+ xmlNewProp(tmp, BAD_CAST "host",
+ BAD_CAST cdev->source_dev.udp.connect_host);
+ /* The service property is not mandatory */
+ if (cdev->source_dev.udp.connect_service)
+ xmlNewProp(tmp, BAD_CAST "service",
+ BAD_CAST
+ cdev->source_dev.udp.connect_service);
+
+ break;
+ case CIM_CHARDEV_SOURCE_TYPE_TCP:
+ tmp = xmlNewChild(console, NULL,
+ BAD_CAST "source", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "mode",
+ BAD_CAST cdev->source_dev.tcp.mode);
+ xmlNewProp(tmp, BAD_CAST "host",
+ BAD_CAST cdev->source_dev.tcp.host);
+ if (cdev->source_dev.tcp.service)
+ xmlNewProp(tmp, BAD_CAST "service",
+ BAD_CAST
+ cdev->source_dev.tcp.service);
+ if (cdev->source_dev.tcp.protocol) {
+ tmp = xmlNewChild(console, NULL,
+ BAD_CAST "protocol", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "type",
+ BAD_CAST cdev->source_dev.tcp.protocol);
+ }
+ break;
+ default:
+ /* Nothing to do for :
+ CIM_CHARDEV_SOURCE_TYPE_STDIO
+ CIM_CHARDEV_SOURCE_TYPE_NULL
+ CIM_CHARDEV_SOURCE_TYPE_VC
+ CIM_CHARDEV_SOURCE_TYPE_SPICEVMC
+ */
+ break;
+ }
+
+ if (cdev->target_type) {
+ tmp = xmlNewChild(console, NULL,
+ BAD_CAST "target", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "type",
+ BAD_CAST cdev->target_type);
+ }
+ }
+ return NULL;
+}
+
static char *disk_block_xml(xmlNodePtr root, struct disk_device *dev)
{
xmlNodePtr disk;
@@ -977,6 +1160,11 @@ char *device_to_xml(struct virt_device *_dev)
dominfo->dev_graphics_ct = 1;
dominfo->dev_graphics = dev;
break;
+ case CIM_RES_TYPE_CONSOLE:
+ func = console_xml;
+ dominfo->dev_console_ct = 1;
+ dominfo->dev_console = dev;
+ break;
case CIM_RES_TYPE_INPUT:
func = input_xml;
dominfo->dev_input_ct = 1;
@@ -1017,6 +1205,7 @@ char *system_to_xml(struct domain *dominfo)
&disk_xml,
&net_xml,
&input_xml,
+ &console_xml,
&graphics_xml,
&emu_xml,
NULL
diff --git a/src/svpc_types.h b/src/svpc_types.h
index 2e4d73f..0f46a86 100644
--- a/src/svpc_types.h
+++ b/src/svpc_types.h
@@ -25,6 +25,7 @@
#define CIM_OPERATIONAL_STATUS 2
#define CIM_RES_TYPE_ALL 0
+#define CIM_RES_TYPE_OTHER 1
#define CIM_RES_TYPE_PROC 3
#define CIM_RES_TYPE_MEM 4
#define CIM_RES_TYPE_NET 10
@@ -34,8 +35,9 @@
#define CIM_RES_TYPE_INPUT 13
#define CIM_RES_TYPE_UNKNOWN 1000
#define CIM_RES_TYPE_IMAGE 32768
+#define CIM_RES_TYPE_CONSOLE 32769
-#define CIM_RES_TYPE_COUNT 6
+#define CIM_RES_TYPE_COUNT 7
const static int cim_res_types[CIM_RES_TYPE_COUNT] =
{CIM_RES_TYPE_NET,
CIM_RES_TYPE_DISK,
@@ -43,6 +45,7 @@ const static int cim_res_types[CIM_RES_TYPE_COUNT] =
CIM_RES_TYPE_PROC,
CIM_RES_TYPE_GRAPHICS,
CIM_RES_TYPE_INPUT,
+ CIM_RES_TYPE_CONSOLE,
};
#define CIM_VSSD_RECOVERY_NONE 2
--
2.1.0