You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
750 lines
29 KiB
750 lines
29 KiB
7 years ago
|
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
|