# HG changeset patch
# User Dan Smith <danms(a)us.ibm.com>
# Date 1228236226 28800
# Node ID c34ae7c0ded8870aeba40a0798ac31f1ea2c5bbd
# Parent 6e8a488cf67b47efb618c28aa2a9104d5b0e1b91
Make xmlgen.c use libxml2 instead of hacking it out manually
Now that our XML generation is getting complex enough, I think it's worth
using libxml2 to build a proper DOM tree and XML string.
Note that due to the invasiveness of this patch, it's almost unreadable. It
may be easier to review after it's applied to the tree. Also, it deserves
some serious review and testing for correctness and error-handling abilities.
Comments on this approach are welcome too, of course.
Signed-off-by: Dan Smith <danms(a)us.ibm.com>
diff -r 6e8a488cf67b -r c34ae7c0ded8 libxkutil/xmlgen.c
--- a/libxkutil/xmlgen.c Mon Dec 01 10:00:45 2008 -0800
+++ b/libxkutil/xmlgen.c Tue Dec 02 08:43:46 2008 -0800
@@ -24,6 +24,8 @@
#include <inttypes.h>
#include <uuid/uuid.h>
+#include <libxml/tree.h>
+
#include "xmlgen.h"
#ifndef TEST
@@ -32,487 +34,378 @@
#include "cmpimacs.h"
#endif
-static char *__tag_attr(struct kv *attrs, int count)
+#define XML_ERROR "Failed to allocate XML memory"
+
+typedef const char *(*devfn_t)(xmlNodePtr node, struct domain *dominfo);
+
+static char *disk_block_xml(xmlNodePtr root, struct disk_device *dev)
{
- char *result = strdup("");
- char *new = NULL;
- int i;
- int size = 0;
+ xmlNodePtr disk;
+ xmlNodePtr tmp;
- for (i = 0; i < count; i++) {
- char *tmp;
- int ret;
+ disk = xmlNewChild(root, NULL, BAD_CAST "disk", NULL);
+ if (disk == NULL)
+ return XML_ERROR;
+ xmlNewProp(disk, BAD_CAST "type", BAD_CAST "block");
+ xmlNewProp(disk, BAD_CAST "device", BAD_CAST dev->device);
- ret = asprintf(&new, " %s='%s'",
- attrs[i].key, attrs[i].val);
+ tmp = xmlNewChild(disk, NULL, BAD_CAST "source", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "dev", BAD_CAST dev->source);
- if (ret == -1)
- goto err;
+ tmp = xmlNewChild(disk, NULL, BAD_CAST "target", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "dev", BAD_CAST dev->virtual_dev);
- size += strlen(new) + 1;
- tmp = realloc(result, size);
- if (tmp == NULL)
- goto err;
+ if (dev->readonly)
+ xmlNewChild(disk, NULL, BAD_CAST "readonly", NULL);
- result = tmp;
-
- strcat(result, new);
- free(new);
- }
-
- return result;
-
- err:
- free(result);
- return NULL;
-}
-
-static char *tagify(char *tagname, char *content, struct kv *attrs, int count)
-{
- char *result;
- int ret;
- char *opentag;
-
- if (count)
- opentag = __tag_attr(attrs, count);
- else
- opentag = strdup("");
-
- if (content)
- ret = asprintf(&result,
- "<%s%s>%s</%s>",
- tagname, opentag, content, tagname);
- else
- ret = asprintf(&result,
- "<%s%s/>", tagname, opentag);
- if (ret == -1)
- result = NULL;
-
- free(opentag);
-
- return result;
-}
-
-static int astrcat(char **dest, char *source)
-{
- char *tmp;
- int ret;
-
- if (*dest) {
- ret = asprintf(&tmp, "%s%s", *dest, source);
- if (ret == -1)
- return 0;
- } else {
- tmp = strdup(source);
- }
-
- free(*dest);
-
- *dest = tmp;
-
- return 1;
-}
-
-static char *disk_block_xml(struct disk_device *dev)
-{
- char *xml;
- int ret;
-
- ret = asprintf(&xml,
- "<disk type='block'
device='%s'>\n"
- " <source dev='%s'/>\n"
- " <target dev='%s'/>\n"
- "%s"
- "%s"
- "</disk>\n",
- dev->device,
- dev->source,
- dev->virtual_dev,
- dev->readonly ? "<readonly/>\n" :
"",
- dev->shareable ? "<shareable/>\n" :
"");
- if (ret == -1)
- xml = NULL;
-
- return xml;
-}
-
-static char *disk_file_xml(struct disk_device *dev)
-{
- char *xml;
- int ret;
-
- ret = asprintf(&xml,
- "<disk type='file'
device='%s'>\n"
- " <source file='%s'/>\n"
- " <target dev='%s'/>\n"
- "%s"
- "%s"
- "</disk>\n",
- dev->device,
- dev->source,
- dev->virtual_dev,
- dev->readonly ? "<readonly/>" : "",
- dev->shareable ? "<shareable/>" :
"");
- if (ret == -1)
- xml = NULL;
-
- return xml;
-}
-
-static char *disk_fs_xml(struct disk_device *dev)
-{
- char *xml;
- int ret;
-
- ret = asprintf(&xml,
- "<filesystem type='mount'>\n"
- " <source dir='%s'/>\n"
- " <target dir='%s'/>\n"
- "</filesystem>\n",
- dev->source,
- dev->virtual_dev);
- if (ret == -1)
- xml = NULL;
-
- return xml;
-}
-
-static bool disk_to_xml(char **xml, struct virt_device *dev)
-{
- char *_xml = NULL;
- struct disk_device *disk = &dev->dev.disk;
-
- if (disk->disk_type == DISK_PHY)
- _xml = disk_block_xml(disk);
- else if (disk->disk_type == DISK_FILE)
- /* If it's not a block device, we assume a file,
- which should be a reasonable fail-safe */
- _xml = disk_file_xml(disk);
- else if (disk->disk_type == DISK_FS)
- _xml = disk_fs_xml(disk);
- else
- return false;
-
- astrcat(xml, _xml);
- free(_xml);
-
- return true;
-}
-
-static bool bridge_net_to_xml(char **xml, struct virt_device *dev)
-{
- int ret;
- char *_xml;
- char *script = "vif-bridge";
- struct net_device *net = &dev->dev.net;
-
- if (net->source == NULL)
- ret = asprintf(&_xml,
- "<interface type='%s'>\n"
- " <mac address='%s'/>\n"
- " <script path='%s'/>\n"
- "</interface>\n",
- net->type,
- net->mac,
- script);
- else
- ret = asprintf(&_xml,
- "<interface type='%s'>\n"
- " <source bridge='%s'/>\n"
- " <mac address='%s'/>\n"
- " <script path='%s'/>\n"
- "</interface>\n",
- net->type,
- net->source,
- net->mac,
- script);
-
- if (ret == -1)
- return false;
- else
- astrcat(xml, _xml);
-
- free(_xml);
-
- return true;
-}
-
-static bool network_net_to_xml(char **xml, struct virt_device *dev)
-{
- int ret;
- char *_xml;
- struct net_device *net = &dev->dev.net;
-
- if (net->source == NULL)
- ret = asprintf(&_xml,
- "<interface type='%s'>\n"
- " <mac address='%s'/>\n"
- "</interface>\n",
- net->type,
- net->mac);
- else
- ret = asprintf(&_xml,
- "<interface type='%s'>\n"
- " <mac address='%s'/>\n"
- " <source network='%s'/>\n"
- "</interface>\n",
- net->type,
- net->mac,
- net->source);
- if (ret == -1)
- return false;
- else
- astrcat(xml, _xml);
-
- free(_xml);
-
- return true;
-}
-
-static bool user_net_to_xml(char **xml, struct virt_device *dev)
-{
- int ret;
- char *_xml;
- struct net_device *net = &dev->dev.net;
-
- ret = asprintf(&_xml,
- "<interface type='%s'>\n"
- " <mac address='%s'/>\n"
- "</interface>\n",
- net->type,
- net->mac);
- if (ret == -1)
- return false;
- else
- astrcat(xml, _xml);
-
- free(_xml);
-
- return true;
-}
-
-static bool net_to_xml(char **xml, struct virt_device *dev)
-{
- if (STREQ(dev->dev.net.type, "network"))
- return network_net_to_xml(xml, dev);
- else if (STREQ(dev->dev.net.type, "bridge"))
- return bridge_net_to_xml(xml, dev);
- else if (STREQ(dev->dev.net.type, "user"))
- return user_net_to_xml(xml, dev);
- else
- return false;
-}
-
-static bool vcpu_to_xml(char **xml, struct virt_device *dev)
-{
- int ret;
- char *_xml;
-
- ret = asprintf(&_xml, "<vcpu>%" PRIu64
"</vcpu>\n",
- dev->dev.vcpu.quantity);
- if (ret == -1)
- return false;
- else
- astrcat(xml, _xml);
-
- return true;
-}
-
-static bool mem_to_xml(char **xml, struct virt_device *dev)
-{
- int ret;
- char *_xml;
- struct mem_device *mem = &dev->dev.mem;
-
- ret = asprintf(&_xml,
- "<currentMemory>%" PRIu64
"</currentMemory>\n"
- "<memory>%" PRIu64 "</memory>\n",
- mem->size,
- mem->maxsize);
-
-
- if (ret == -1)
- return false;
- else
- astrcat(xml, _xml);
-
- free(_xml);
-
- return true;
-}
-
-static bool emu_to_xml(char **xml, struct virt_device *dev)
-{
- int ret;
- char *_xml;
- struct emu_device *emu = &dev->dev.emu;
-
- ret = asprintf(&_xml,
- "<emulator>%s</emulator>\n",
- emu->path);
- if (ret == -1)
- return false;
- else
- astrcat(xml, _xml);
-
- free(_xml);
-
- return true;
-}
-
-static bool graphics_to_xml(char **xml, struct virt_device *dev)
-{
- int ret;
- char *_xml;
- struct graphics_device *graphics = &dev->dev.graphics;
-
- ret = asprintf(&_xml,
- "<graphics type='%s' port='%s' "
- "listen='%s' keymap='%s'/>\n",
- graphics->type,
- graphics->port,
- graphics->host != NULL ? graphics->host :
"127.0.0.1",
- graphics->keymap != NULL ? graphics->keymap :
"en-us");
- if (ret == -1)
- return false;
- else
- astrcat(xml, _xml);
-
- free(_xml);
-
- return true;
-}
-
-static bool input_to_xml(char **xml, struct virt_device *dev)
-{
- int ret;
- char *_xml;
- struct input_device *input = &dev->dev.input;
-
- ret = asprintf(&_xml,
- "<input type='%s' bus='%s'/>\n",
- input->type != NULL ? input->type: "mouse",
- input->bus != NULL ? input->bus : "ps2");
- if (ret == -1)
- return false;
- else
- astrcat(xml, _xml);
-
- free(_xml);
-
- return true;
-}
-
-static bool concat_devxml(char **xml,
- struct virt_device *list,
- int count,
- bool (*func)(char **, struct virt_device *))
-{
- char *_xml = NULL;
- int i;
-
- for (i = 0; i < count; i++) {
- /* Deleted devices are marked as CIM_RES_TYPE_UNKNOWN
- * and should be skipped
- */
- if (list[i].type != CIM_RES_TYPE_UNKNOWN)
- func(&_xml, &list[i]);
- }
-
- if (_xml != NULL)
- astrcat(xml, _xml);
- free(_xml);
-
- return true;
-}
-
-char *device_to_xml(struct virt_device *dev)
-{
- char *xml = NULL;
- int type = dev->type;
- bool (*func)(char **, struct virt_device *);
-
- switch (type) {
- case CIM_RES_TYPE_DISK:
- func = disk_to_xml;
- break;
- case CIM_RES_TYPE_PROC:
- func = vcpu_to_xml;
- break;
- case CIM_RES_TYPE_NET:
- func = net_to_xml;
- break;
- case CIM_RES_TYPE_MEM:
- func = mem_to_xml;
- break;
- case CIM_RES_TYPE_EMU:
- func = emu_to_xml;
- break;
- case CIM_RES_TYPE_GRAPHICS:
- func = graphics_to_xml;
- break;
- case CIM_RES_TYPE_INPUT:
- func = input_to_xml;
- break;
- default:
- return NULL;
- }
-
- if (concat_devxml(&xml, dev, 1, func))
- return xml;
-
- free(xml);
+ if (dev->shareable)
+ xmlNewChild(disk, NULL, BAD_CAST "shareable", NULL);
return NULL;
}
-static char *system_xml(struct domain *domain)
+static const char *disk_file_xml(xmlNodePtr root, struct disk_device *dev)
{
- int ret;
- char *bl = NULL;
- char *bl_args = NULL;
- char *xml;
+ xmlNodePtr disk;
+ xmlNodePtr tmp;
- if (domain->bootloader)
- bl = tagify("bootloader",
- domain->bootloader,
- NULL,
- 0);
- if (domain->bootloader_args)
- bl_args = tagify("bootloader_args",
- domain->bootloader_args,
- NULL,
- 0);
+ disk = xmlNewChild(root, NULL, BAD_CAST "disk", NULL);
+ if (disk == NULL)
+ return XML_ERROR;
+ xmlNewProp(disk, BAD_CAST "type", BAD_CAST "file");
+ xmlNewProp(disk, BAD_CAST "device", BAD_CAST dev->device);
- ret = asprintf(&xml,
- "<name>%s</name>\n"
- "%s\n"
- "%s\n"
- "<on_poweroff>%s</on_poweroff>\n"
- "<on_crash>%s</on_crash>\n",
- domain->name,
- bl ? bl : "",
- bl_args ? bl_args : "",
- vssd_recovery_action_str(domain->on_poweroff),
- vssd_recovery_action_str(domain->on_crash));
- if (ret == -1)
- xml = NULL;
+ tmp = xmlNewChild(disk, NULL, BAD_CAST "source", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "file", BAD_CAST dev->source);
- free(bl);
- free(bl_args);
+ tmp = xmlNewChild(disk, NULL, BAD_CAST "target", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "dev", BAD_CAST dev->virtual_dev);
- return xml;
+ if (dev->readonly)
+ xmlNewChild(disk, NULL, BAD_CAST "readonly", NULL);
+
+ if (dev->shareable)
+ xmlNewChild(disk, NULL, BAD_CAST "shareable", NULL);
+
+
+ return NULL;
}
-static char *_xenpv_os_xml(struct domain *domain)
+static const char *disk_fs_xml(xmlNodePtr root, struct disk_device *dev)
+{
+ xmlNodePtr fs;
+ xmlNodePtr tmp;
+
+ fs = xmlNewChild(root, NULL, BAD_CAST "filesystem", NULL);
+ if (fs == NULL)
+ return XML_ERROR;
+
+ tmp = xmlNewChild(fs, NULL, BAD_CAST "source", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "dir", BAD_CAST dev->source);
+
+ tmp = xmlNewChild(fs, NULL, BAD_CAST "target", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "dir", BAD_CAST dev->virtual_dev);
+
+ return NULL;
+}
+
+static const char *disk_xml(xmlNodePtr root, struct domain *dominfo)
+{
+ int i;
+ const char *msg = NULL;;
+
+ for (i = 0; (i < dominfo->dev_disk_ct) && (msg == NULL); i++) {
+ struct disk_device *disk = &dominfo->dev_disk[i].dev.disk;
+ CU_DEBUG("Disk: %i %s %s",
+ disk->disk_type,
+ disk->source,
+ disk->virtual_dev);
+ if (disk->disk_type == DISK_PHY)
+ msg = disk_block_xml(root, disk);
+ else if (disk->disk_type == DISK_FILE)
+ /* If it's not a block device, we assume a file,
+ which should be a reasonable fail-safe */
+ msg = disk_file_xml(root, disk);
+ else if (disk->disk_type == DISK_FS)
+ msg = disk_fs_xml(root, disk);
+ else
+ msg = "Unknown disk type";
+ }
+
+ return msg;
+}
+
+static const char *bridge_net_to_xml(xmlNodePtr root, struct net_device *dev)
+{
+ const char *script = "vif-bridge";
+ xmlNodePtr nic;
+ xmlNodePtr tmp;
+
+ nic = xmlNewChild(root, NULL, BAD_CAST "interface", NULL);
+ if (nic == NULL)
+ return XML_ERROR;
+ xmlNewProp(nic, BAD_CAST "type", BAD_CAST dev->type);
+
+ tmp = xmlNewChild(nic, NULL, BAD_CAST "mac", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "address", BAD_CAST dev->mac);
+
+ tmp = xmlNewChild(nic, NULL, BAD_CAST "script", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "path", BAD_CAST script);
+
+ if (dev->source != NULL) {
+ tmp = xmlNewChild(nic, NULL, BAD_CAST "source", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "bridge", BAD_CAST dev->source);
+ }
+
+ return NULL;
+}
+
+static const char *network_net_to_xml(xmlNodePtr root, struct net_device *dev)
+{
+ xmlNodePtr nic;
+ xmlNodePtr tmp;
+
+ nic = xmlNewChild(root, NULL, BAD_CAST "interface", NULL);
+ if (nic == NULL)
+ return XML_ERROR;
+ xmlNewProp(nic, BAD_CAST "type", BAD_CAST dev->type);
+
+ tmp = xmlNewChild(nic, NULL, BAD_CAST "mac", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "address", BAD_CAST dev->mac);
+
+ if (dev->source != NULL) {
+ tmp = xmlNewChild(nic, NULL, BAD_CAST "source", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "network", BAD_CAST dev->source);
+ }
+
+ return NULL;
+}
+
+static const char *user_net_to_xml(xmlNodePtr root, struct net_device *dev)
+{
+ xmlNodePtr nic;
+ xmlNodePtr tmp;
+
+ nic = xmlNewChild(root, NULL, BAD_CAST "interface", NULL);
+ if (nic == NULL)
+ return XML_ERROR;
+ xmlNewProp(nic, BAD_CAST "type", BAD_CAST dev->type);
+
+ tmp = xmlNewChild(nic, NULL, BAD_CAST "mac", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "address", BAD_CAST dev->mac);
+
+ return NULL;
+}
+
+static const char *net_xml(xmlNodePtr root, struct domain *dominfo)
+{
+ int i;
+ const char *msg = NULL;
+
+ for (i = 0; (i < dominfo->dev_net_ct) && (msg == NULL); i++) {
+ struct virt_device *dev = &dominfo->dev_net[i];
+ struct net_device *net = &dev->dev.net;
+
+ if (STREQ(dev->dev.net.type, "network"))
+ msg = network_net_to_xml(root, net);
+ else if (STREQ(dev->dev.net.type, "bridge"))
+ msg = bridge_net_to_xml(root, net);
+ else if (STREQ(dev->dev.net.type, "user"))
+ msg = user_net_to_xml(root, net);
+ else
+ msg = "Unknown interface type";
+ }
+
+ return msg;
+}
+
+static const char *vcpu_xml(xmlNodePtr root, struct domain *dominfo)
+{
+ struct vcpu_device *vcpu;
+ xmlNodePtr tmp;
+ int ret;
+ char *string = NULL;
+
+ if (dominfo->dev_vcpu == NULL)
+ return NULL;
+
+ vcpu = &dominfo->dev_vcpu[0].dev.vcpu;
+
+ ret = asprintf(&string, "%" PRIu64, vcpu->quantity);
+ if (ret == -1)
+ return XML_ERROR;
+
+ tmp = xmlNewChild(root, NULL, BAD_CAST "vcpu", BAD_CAST string);
+ free(string);
+
+ if (tmp == NULL)
+ return XML_ERROR;
+ else
+ return NULL;
+}
+
+static const char *mem_xml(xmlNodePtr root, struct domain *dominfo)
+{
+ struct mem_device *mem;
+ xmlNodePtr tmp = NULL;
+ int ret;
+ char *string = NULL;
+
+ if (dominfo->dev_mem == NULL)
+ return NULL;
+
+ mem = &dominfo->dev_mem[0].dev.mem;
+
+ ret = asprintf(&string, "%" PRIu64, mem->size);
+ if (ret == -1)
+ goto out;
+ tmp = xmlNewChild(root,
+ NULL,
+ BAD_CAST "currentMemory",
+ BAD_CAST string);
+
+ free(string);
+ tmp = NULL;
+
+ ret = asprintf(&string, "%" PRIu64, mem->maxsize);
+ if (ret == -1)
+ goto out;
+ tmp = xmlNewChild(root,
+ NULL,
+ BAD_CAST "memory",
+ BAD_CAST string);
+
+ free(string);
+ out:
+ if (tmp == NULL)
+ return XML_ERROR;
+ else
+ return NULL;
+}
+
+static const char *emu_xml(xmlNodePtr root, struct domain *dominfo)
+{
+ struct emu_device *emu;
+ xmlNodePtr tmp;
+
+ if (dominfo->dev_emu == NULL)
+ return NULL;
+
+ emu = &dominfo->dev_emu->dev.emu;
+ tmp = xmlNewChild(root, NULL, BAD_CAST "emulator", BAD_CAST
emu->path);
+ if (tmp == NULL)
+ return XML_ERROR;
+
+ return NULL;
+}
+
+static const char *graphics_xml(xmlNodePtr root, struct domain *dominfo)
+{
+ int i;
+
+ for (i = 0; i < dominfo->dev_graphics_ct; i++) {
+ xmlNodePtr tmp;
+ struct virt_device *_dev = &dominfo->dev_graphics[i];
+ struct graphics_device *dev = &_dev->dev.graphics;
+
+ tmp = xmlNewChild(root, NULL, BAD_CAST "graphics", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+
+ xmlNewProp(tmp, BAD_CAST "type", BAD_CAST dev->type);
+ xmlNewProp(tmp, BAD_CAST "port", BAD_CAST dev->port);
+ xmlNewProp(tmp, BAD_CAST "listen", BAD_CAST dev->host);
+ xmlNewProp(tmp, BAD_CAST "keymap", BAD_CAST dev->keymap);
+ }
+
+ return NULL;
+}
+
+static const char *input_xml(xmlNodePtr root, struct domain *dominfo)
+{
+ int i;
+
+ for (i = 0; i < dominfo->dev_input_ct; i++) {
+ xmlNodePtr tmp;
+ struct virt_device *_dev = &dominfo->dev_input[i];
+ struct input_device *dev = &_dev->dev.input;
+
+ tmp = xmlNewChild(root, NULL, BAD_CAST "input", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+
+ xmlNewProp(tmp, BAD_CAST "type", BAD_CAST dev->type);
+ xmlNewProp(tmp, BAD_CAST "bus", BAD_CAST dev->bus);
+ }
+
+ return NULL;
+}
+
+static char *system_xml(xmlNodePtr root, struct domain *domain)
+{
+ xmlNodePtr tmp;
+
+ tmp = xmlNewChild(root, NULL, BAD_CAST "name", BAD_CAST
domain->name);
+
+ if (domain->bootloader) {
+ xmlNodePtr bl;
+
+ bl = xmlNewChild(root,
+ NULL,
+ BAD_CAST "bootloader",
+ BAD_CAST domain->bootloader);
+ }
+
+ if (domain->bootloader_args) {
+ xmlNodePtr bl_args;
+
+ bl_args = xmlNewChild(root,
+ NULL,
+ BAD_CAST "bootloader_args",
+ BAD_CAST domain->bootloader_args);
+ }
+
+ tmp = xmlNewChild(root,
+ NULL,
+ BAD_CAST "on_poweroff",
+ BAD_CAST vssd_recovery_action_str(domain->on_poweroff));
+
+ tmp = xmlNewChild(root,
+ NULL,
+ BAD_CAST "on_crash",
+ BAD_CAST vssd_recovery_action_str(domain->on_crash));
+
+ return NULL;
+}
+
+static char *_xenpv_os_xml(xmlNodePtr root, struct domain *domain)
{
struct pv_os_info *os = &domain->os_info.pv;
- int ret;
- char *xml;
- char *type = NULL;
- char *kernel = NULL;
- char *initrd = NULL;
- char *cmdline = NULL;
+ xmlNodePtr tmp;
if (os->type == NULL)
os->type = strdup("linux");
@@ -520,42 +413,29 @@
if (os->kernel == NULL)
os->kernel = strdup("/dev/null");
- type = tagify("type", os->type, NULL, 0);
- kernel = tagify("kernel", os->kernel, NULL, 0);
- initrd = tagify("initrd", os->initrd, NULL, 0);
- cmdline = tagify("cmdline", os->cmdline, NULL, 0);
+ tmp = xmlNewChild(root, NULL, BAD_CAST "type", BAD_CAST os->type);
+ if (tmp == NULL)
+ return XML_ERROR;
- ret = asprintf(&xml,
- "<os>\n"
- " %s\n"
- " %s\n"
- " %s\n"
- " %s\n"
- "</os>\n",
- type,
- kernel,
- initrd,
- cmdline);
- if (ret == -1)
- xml = NULL;
+ tmp = xmlNewChild(root, NULL, BAD_CAST "kernel", BAD_CAST
os->kernel);
+ if (tmp == NULL)
+ return XML_ERROR;
- free(type);
- free(kernel);
- free(initrd);
- free(cmdline);
+ tmp = xmlNewChild(root, NULL, BAD_CAST "initrd", BAD_CAST
os->initrd);
+ if (tmp == NULL)
+ return XML_ERROR;
- return xml;
+ tmp = xmlNewChild(root, NULL, BAD_CAST "cmdline", BAD_CAST
os->cmdline);
+ if (tmp == NULL)
+ return XML_ERROR;
+
+ return NULL;
}
-static char *_xenfv_os_xml(struct domain *domain)
+static char *_xenfv_os_xml(xmlNodePtr root, struct domain *domain)
{
struct fv_os_info *os = &domain->os_info.fv;
- int ret;
- char *xml;
- char *type;
- char *loader;
- char *boot;
- struct kv bootattr = {"dev", NULL};
+ xmlNodePtr tmp;
if (os->type == NULL)
os->type = strdup("hvm");
@@ -566,44 +446,30 @@
if (os->boot == NULL)
os->boot = strdup("hd");
- type = tagify("type", os->type, NULL, 0);
- loader = tagify("loader", os->loader, NULL, 0);
+ tmp = xmlNewChild(root, NULL, BAD_CAST "type", BAD_CAST os->type);
+ if (tmp == NULL)
+ return XML_ERROR;
- bootattr.val = os->boot;
- boot = tagify("boot", NULL, &bootattr, 1);
+ tmp = xmlNewChild(root, NULL, BAD_CAST "loader", BAD_CAST
os->loader);
+ if (tmp == NULL)
+ return XML_ERROR;
- ret = asprintf(&xml,
- "<os>\n"
- " %s\n"
- " %s\n"
- " %s\n"
- "</os>\n"
- "<features>\n"
- " <pae/>\n"
- " <acpi/>\n"
- " <apic/>\n"
- "</features>\n",
- type,
- loader,
- boot);
- if (ret == -1)
- xml = NULL;
+ tmp = xmlNewChild(root, NULL, BAD_CAST "boot", BAD_CAST os->boot);
+ if (tmp == NULL)
+ return XML_ERROR;
- free(type);
- free(loader);
- free(boot);
+ tmp = xmlNewChild(root, NULL, BAD_CAST "features", NULL);
+ xmlNewChild(tmp, NULL, BAD_CAST "pae", NULL);
+ xmlNewChild(tmp, NULL, BAD_CAST "acpi", NULL);
+ xmlNewChild(tmp, NULL, BAD_CAST "apic", NULL);
- return xml;
+ return NULL;
}
-static char *_kvm_os_xml(struct domain *domain)
+static char *_kvm_os_xml(xmlNodePtr root, struct domain *domain)
{
struct fv_os_info *os = &domain->os_info.fv;
- int ret;
- char *xml;
- char *type;
- char *boot;
- struct kv bootattr = {"dev", NULL};
+ xmlNodePtr tmp;
if (os->type == NULL)
os->type = strdup("hvm");
@@ -611,84 +477,162 @@
if (os->boot == NULL)
os->boot = strdup("hd");
- type = tagify("type", os->type, NULL, 0);
+ tmp = xmlNewChild(root, NULL, BAD_CAST "type", BAD_CAST os->type);
+ if (tmp == NULL)
+ return XML_ERROR;
- bootattr.val = os->boot;
- boot = tagify("boot", NULL, &bootattr, 1);
+ tmp = xmlNewChild(root, NULL, BAD_CAST "boot", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "dev", BAD_CAST os->boot);
- ret = asprintf(&xml,
- "<os>\n"
- " %s\n"
- " %s\n"
- "</os>\n",
- type,
- boot);
- if (ret == -1)
- xml = NULL;
+ return NULL;
+}
- free(type);
- free(boot);
+static char *_lxc_os_xml(xmlNodePtr root, struct domain *domain)
+{
+ struct lxc_os_info *os = &domain->os_info.lxc;
+ xmlNodePtr tmp;
+
+ if (os->type == NULL)
+ os->type = strdup("exe");
+
+ tmp = xmlNewChild(root, NULL, BAD_CAST "init", BAD_CAST os->init);
+ if (tmp == NULL)
+ return XML_ERROR;
+
+ tmp = xmlNewChild(root, NULL, BAD_CAST "type", BAD_CAST os->type);
+ if (tmp == NULL)
+ return XML_ERROR;
+
+ return NULL;
+}
+
+static char *os_xml(xmlNodePtr root, struct domain *domain)
+{
+ xmlNodePtr os;
+
+ os = xmlNewChild(root, NULL, BAD_CAST "os", NULL);
+ if (os == NULL)
+ return "Failed to allocate XML memory";
+
+ if (domain->type == DOMAIN_XENPV)
+ return _xenpv_os_xml(os, domain);
+ else if (domain->type == DOMAIN_XENFV)
+ return _xenfv_os_xml(os, domain);
+ else if (domain->type == DOMAIN_KVM)
+ return _kvm_os_xml(os, domain);
+ else if (domain->type == DOMAIN_LXC)
+ return _lxc_os_xml(os, domain);
+ else
+ return "Unsupported domain type";
+}
+
+char *device_to_xml(struct virt_device *dev)
+{
+ char *xml = NULL;
+ int type = dev->type;
+ xmlDocPtr doc = NULL;
+ xmlNodePtr root = NULL;
+ xmlChar *_xml = NULL;
+ int xml_size;
+ const char *msg;
+ struct domain *dominfo;
+ devfn_t func;
+
+ dominfo = calloc(1, sizeof(*dominfo));
+ if (dominfo == NULL)
+ return NULL;
+
+ doc = xmlNewDoc(BAD_CAST "1.0");
+ if (doc == NULL)
+ goto out;
+ root = xmlNewNode(NULL, BAD_CAST "tmp");
+ if (root == NULL)
+ goto out;
+
+ switch (type) {
+ case CIM_RES_TYPE_DISK:
+ func = disk_xml;
+ dominfo->dev_disk_ct = 1;
+ dominfo->dev_disk = dev;
+ break;
+ case CIM_RES_TYPE_PROC:
+ func = vcpu_xml;
+ dominfo->dev_vcpu_ct = 1;
+ dominfo->dev_vcpu = dev;
+ break;
+ case CIM_RES_TYPE_NET:
+ func = net_xml;
+ dominfo->dev_net_ct = 1;
+ dominfo->dev_vcpu = dev;
+ break;
+ case CIM_RES_TYPE_MEM:
+ func = mem_xml;
+ dominfo->dev_mem_ct = 1;
+ dominfo->dev_mem = dev;
+ break;
+ case CIM_RES_TYPE_EMU:
+ func = emu_xml;
+ dominfo->dev_emu = dev;
+ break;
+ case CIM_RES_TYPE_GRAPHICS:
+ func = graphics_xml;
+ dominfo->dev_graphics_ct = 1;
+ dominfo->dev_graphics = dev;
+ break;
+ case CIM_RES_TYPE_INPUT:
+ func = input_xml;
+ dominfo->dev_input_ct = 1;
+ dominfo->dev_input = dev;
+ break;
+ default:
+ return NULL;
+ }
+
+ msg = func(root, dominfo);
+ if (msg != NULL) {
+ CU_DEBUG("Failed to create device XML: %s", msg);
+ goto out;
+ }
+
+ xmlDocSetRootElement(doc, root->children);
+
+ xmlDocDumpFormatMemory(doc, &_xml, &xml_size, 1);
+ xml = strdup((char *)_xml);
+ xmlFree(_xml);
+ out:
+ CU_DEBUG("Created Device XML:\n%s\n", xml);
+
+ cleanup_dominfo(&dominfo);
+ xmlFreeNode(root);
+ xmlFreeDoc(doc);
return xml;
}
-static char *_lxc_os_xml(struct domain *domain)
-{
- struct lxc_os_info *os = &domain->os_info.lxc;
- int ret;
- char *xml = NULL;
-
- if (os->type == NULL)
- os->type = strdup("exe");
-
- ret = asprintf(&xml,
- "<os>\n"
- " <init>%s</init>\n"
- " <type>%s</type>\n"
- "</os>\n",
- os->init,
- os->type);
- if (ret == -1)
- xml = NULL;
-
- return xml;
-}
-
-static char *os_xml(struct domain *domain)
-{
- if (domain->type == DOMAIN_XENPV)
- return _xenpv_os_xml(domain);
- else if (domain->type == DOMAIN_XENFV)
- return _xenfv_os_xml(domain);
- else if (domain->type == DOMAIN_KVM)
- return _kvm_os_xml(domain);
- else if (domain->type == DOMAIN_LXC)
- return _lxc_os_xml(domain);
- else
- return strdup("<!-- unsupported domain type -->\n");
-}
-
-static int console_xml(struct domain *dominfo,
- char **xml)
-{
- if (dominfo->type == DOMAIN_LXC) {
- astrcat(xml, "<console type='pty'/>\n");
- }
-
- return 0;
-}
char *system_to_xml(struct domain *dominfo)
{
- char *devxml = strdup("");
- char *sysdevxml = strdup("");
- char *sysxml = NULL;
- char *osxml = NULL;
+ xmlDocPtr doc = NULL;
+ xmlNodePtr root = NULL;
+ xmlNodePtr devices = NULL;
+ xmlChar *_xml = NULL;
char *xml = NULL;
- int ret;
+ int xml_len;
uint8_t uuid[16];
char uuidstr[37];
const char *domtype;
+ const char *msg = XML_ERROR;
+ int i;
+ devfn_t device_handlers[] = {
+ &disk_xml,
+ &net_xml,
+ &input_xml,
+ &graphics_xml,
+ &emu_xml,
+ NULL
+ };
if ((dominfo->type == DOMAIN_XENPV) || (dominfo->type == DOMAIN_XENFV))
domtype = "xen";
@@ -708,70 +652,92 @@
uuid_unparse(uuid, uuidstr);
}
- concat_devxml(&devxml,
- dominfo->dev_net,
- dominfo->dev_net_ct,
- net_to_xml);
- concat_devxml(&devxml,
- dominfo->dev_disk,
- dominfo->dev_disk_ct,
- disk_to_xml);
+ CU_DEBUG("foo");
+ doc = xmlNewDoc(BAD_CAST "1.0");
+ if (doc == NULL)
+ goto out;
- if (dominfo->dev_emu)
- concat_devxml(&devxml,
- dominfo->dev_emu,
- 1,
- emu_to_xml);
+ CU_DEBUG("foo");
+ root = xmlNewNode(NULL, BAD_CAST "domain");
+ if (root == NULL)
+ goto out;
- if (dominfo->dev_graphics)
- concat_devxml(&devxml,
- dominfo->dev_graphics,
- dominfo->dev_graphics_ct,
- graphics_to_xml);
+ CU_DEBUG("foo");
+ if (xmlNewProp(root, BAD_CAST "type", BAD_CAST domtype) == NULL)
+ goto out;
- if (dominfo->dev_input)
- concat_devxml(&devxml,
- dominfo->dev_input,
- dominfo->dev_input_ct,
- input_to_xml);
+ CU_DEBUG("foo");
+ xmlDocSetRootElement(doc, root);
- console_xml(dominfo, &devxml);
+ CU_DEBUG("foo");
+ msg = system_xml(root, dominfo);
+ if (msg != NULL)
+ goto out;
- concat_devxml(&sysdevxml,
- dominfo->dev_mem,
- dominfo->dev_mem_ct,
- mem_to_xml);
- concat_devxml(&sysdevxml,
- dominfo->dev_vcpu,
- dominfo->dev_vcpu_ct,
- vcpu_to_xml);
+ CU_DEBUG("foo");
+ msg = os_xml(root, dominfo);
+ if (msg != NULL)
+ goto out;
- sysxml = system_xml(dominfo);
- osxml = os_xml(dominfo);
+ CU_DEBUG("foo");
+ msg = mem_xml(root, dominfo);
+ if (msg != NULL)
+ goto out;
- ret = asprintf(&xml,
- "<domain type='%s'>\n"
- "<uuid>%s</uuid>\n"
- "%s"
- "%s"
- "%s"
- "<devices>\n"
- "%s"
- "</devices>\n"
- "</domain>\n",
- domtype,
- uuidstr,
- sysxml,
- osxml,
- sysdevxml,
- devxml);
- if (ret == -1)
- xml = NULL;
+ CU_DEBUG("foo");
+ msg = vcpu_xml(root, dominfo);
+ if (msg != NULL)
+ goto out;
- free(devxml);
- free(sysdevxml);
- free(osxml);
- free(sysxml);
+ CU_DEBUG("foo");
+ devices = xmlNewChild(root, NULL, BAD_CAST "devices", NULL);
+ if (devices == NULL) {
+ msg = XML_ERROR;
+ goto out;
+ }
+
+ CU_DEBUG("foo");
+ for (i = 0; device_handlers[i] != NULL; i++) {
+ devfn_t fn = device_handlers[i];
+
+ msg = fn(devices, dominfo);
+ if (msg != NULL)
+ goto out;
+ }
+
+ CU_DEBUG("foo");
+ msg = XML_ERROR;
+ if (dominfo->type == DOMAIN_LXC) {
+ xmlNodePtr cons;
+
+ cons = xmlNewChild(devices, NULL, BAD_CAST "console", NULL);
+ if (cons == NULL)
+ goto out;
+
+ if (xmlNewProp(cons, BAD_CAST "type", BAD_CAST "pty")
== NULL)
+ goto out;
+ }
+
+ CU_DEBUG("Generating XML");
+ xmlDocDumpFormatMemory(doc, &_xml, &xml_len, 1);
+ if (_xml == NULL)
+ goto out;
+
+ xml = strdup((char *)_xml);
+ if (xml == NULL)
+ msg = "Out of memory generating XML";
+ else
+ msg = NULL;
+
+ xmlFree(_xml);
+ out:
+ if (msg != NULL) {
+ CU_DEBUG("Failed to create XML: %s", msg);
+ } else {
+ CU_DEBUG("Created System XML:\n%s\n", xml);
+ }
+
+ xmlFreeDoc(doc);
return xml;
}