]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Switch QEMU driver over to generic domain APIs
authorDaniel P. Berrange <berrange@redhat.com>
Fri, 11 Jul 2008 19:34:11 +0000 (19:34 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Fri, 11 Jul 2008 19:34:11 +0000 (19:34 +0000)
12 files changed:
ChangeLog
src/bridge.c
src/bridge.h
src/qemu_conf.c
src/qemu_conf.h
src/qemu_driver.c
tests/qemuxml2argvdata/qemuxml2argv-bootloader.xml
tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc.xml
tests/qemuxml2argvdata/qemuxml2argv-input-xen.xml
tests/qemuxml2argvdata/qemuxml2argv-sound.xml
tests/qemuxml2argvtest.c
tests/qemuxml2xmltest.c

index 8e332df7a15a09ba6970f0b03a54fea6122d66c5..f7d6bdd11f24d6d61579ee705eb37451637441ad 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Fri Jul 11 20:32:59 BST 2008 Daniel P. Berrange <berrange@redhat.com>
+
+       * src/qemu_conf.c, src/qemu_conf.h, src/qemu_driver.c: Switch
+       over to generic domain APIs
+       * src/bridge.c, src/bridge.h: Allocate tap device string on
+       demand.
+       * tests/qemuxml2argvtest.c, tests/qemuxml2xmltest.c: Update
+       to new APIs
+       * tests/qemuxml2argvdata/: Update data files to match new
+       XML generation format
+
 Fri Jul 11 20:28:59 BST 2008 Daniel P. Berrange <berrange@redhat.com>
 
        * src/domain_conf.c: Set state to SHUTOFF when loading domain
@@ -8,15 +19,6 @@ Fri Jul 11 18:58:59 BST 2008 Daniel P. Berrange <berrange@redhat.com>
        * src/network_conf.c, src/domain_conf.c: Use full path when
        opening XML files
 
-Fri Jul 11 18:34:59 BST 2008 Daniel P. Berrange <berrange@redhat.com>
-
-       * src/qemu_conf.c, src/qemu_conf.h, src/qemu_driver.c: Switch
-       over to generic domain APIs
-       * tests/qemuxml2argvtest.c, tests/qemuxml2xmltest.c: Update
-       to new APIs
-       * tests/qemuxml2argvdata/: Update data files to match new
-       XML generation format
-
 Fri Jul 11 18:32:59 BST 2008 Daniel P. Berrange <berrange@redhat.com>
 
        * src/bridge.c, src/bridge.h, src/qemu_conf.c, src/qemu_conf.h,
index 9a77f2b981f5e4f4dc903c5877d7a5345fa4dadc..ea5d5ab8b603378b68b83ca18a4eb3afc3c0a62f 100644 (file)
@@ -281,7 +281,6 @@ brDeleteInterface(brControl *ctl ATTRIBUTE_UNUSED,
  * @ctl: bridge control pointer
  * @bridge: the bridge name
  * @ifname: the interface name (or name template)
- * @maxlen: size of @ifname array
  * @tapfd: file descriptor return value for the new tap device
  *
  * This function creates a new tap device on a bridge. @ifname can be either
@@ -294,8 +293,7 @@ brDeleteInterface(brControl *ctl ATTRIBUTE_UNUSED,
 int
 brAddTap(brControl *ctl,
          const char *bridge,
-         char *ifname,
-         int maxlen,
+         char **ifname,
          int *tapfd)
 {
     int id, subst, fd;
@@ -305,7 +303,7 @@ brAddTap(brControl *ctl,
 
     subst = id = 0;
 
-    if (strstr(ifname, "%d"))
+    if (strstr(*ifname, "%d"))
         subst = 1;
 
     if ((fd = open("/dev/net/tun", O_RDWR)) < 0)
@@ -320,19 +318,19 @@ brAddTap(brControl *ctl,
         try.ifr_flags = IFF_TAP|IFF_NO_PI;
 
         if (subst) {
-            len = snprintf(try.ifr_name, maxlen, ifname, id);
-            if (len >= maxlen) {
+            len = snprintf(try.ifr_name, BR_IFNAME_MAXLEN, *ifname, id);
+            if (len >= BR_IFNAME_MAXLEN) {
                 errno = EADDRINUSE;
                 goto error;
             }
         } else {
-            len = strlen(ifname);
-            if (len >= maxlen - 1) {
+            len = strlen(*ifname);
+            if (len >= BR_IFNAME_MAXLEN - 1) {
                 errno = EINVAL;
                 goto error;
             }
 
-            strncpy(try.ifr_name, ifname, len);
+            strncpy(try.ifr_name, *ifname, len);
             try.ifr_name[len] = '\0';
         }
 
@@ -341,8 +339,11 @@ brAddTap(brControl *ctl,
                 goto error;
             if ((errno = brSetInterfaceUp(ctl, try.ifr_name, 1)))
                 goto error;
-            if (ifname)
-                strncpy(ifname, try.ifr_name, maxlen);
+            VIR_FREE(*ifname);
+            if (!(*ifname = strdup(try.ifr_name))) {
+                errno = ENOMEM;
+                goto error;
+            }
             *tapfd = fd;
             return 0;
         }
index ac4559b4b14b8c8221b22cf04b712bc46ba301cf..03076e3b7c8082e3e94f1a8a69dd25fcb49a4104 100644 (file)
@@ -60,8 +60,7 @@ int     brDeleteInterface       (brControl *ctl,
 
 int     brAddTap                (brControl *ctl,
                                  const char *bridge,
-                                 char *ifname,
-                                 int maxlen,
+                                 char **ifname,
                                  int *tapfd);
 
 int     brSetInterfaceUp        (brControl *ctl,
index d0fc77758196ff93f0ec69524de9c592b1582b20..02b702e7def07ef918495f548849a184ee456423 100644 (file)
 #include <arpa/inet.h>
 #include <sys/utsname.h>
 
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/xpath.h>
-#include <libxml/uri.h>
-
 #if HAVE_NUMACTL
 #include <numa.h>
 #endif
 
-#include "internal.h"
 #include "qemu_conf.h"
 #include "uuid.h"
 #include "buf.h"
 #include "memory.h"
 #include "verify.h"
 #include "c-ctype.h"
-#include "xml.h"
+
+VIR_ENUM_DECL(virDomainDiskQEMUBus)
+VIR_ENUM_IMPL(virDomainDiskQEMUBus, VIR_DOMAIN_DISK_BUS_LAST,
+              "ide",
+              "floppy",
+              "scsi",
+              "virtio",
+              "xen")
+
 
 #define qemudLog(level, msg...) fprintf(stderr, msg)
 
@@ -64,12 +66,12 @@ void qemudReportError(virConnectPtr conn,
                       virNetworkPtr net,
                       int code, const char *fmt, ...) {
     va_list args;
-    char errorMessage[QEMUD_MAX_ERROR_LEN];
+    char errorMessage[1024];
     const char *virerr;
 
     if (fmt) {
         va_start(args, fmt);
-        vsnprintf(errorMessage, QEMUD_MAX_ERROR_LEN-1, fmt, args);
+        vsnprintf(errorMessage, sizeof(errorMessage)-1, fmt, args);
         va_end(args);
     } else {
         errorMessage[0] = '\0';
@@ -86,7 +88,11 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
     virConfValuePtr p;
 
     /* Setup 2 critical defaults */
-    strcpy(driver->vncListen, "127.0.0.1");
+    if (!(driver->vncListen = strdup("127.0.0.1"))) {
+        qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY,
+                         "%s", _("failed to allocate vncListen"));
+        return -1;
+    }
     if (!(driver->vncTLSx509certdir = strdup(SYSCONF_DIR "/pki/libvirt-vnc"))) {
         qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY,
                          "%s", _("failed to allocate vncTLSx509certdir"));
@@ -133,105 +139,18 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
     p = virConfGetValue (conf, "vnc_listen");
     CHECK_TYPE ("vnc_listen", VIR_CONF_STRING);
     if (p && p->str) {
-        strncpy(driver->vncListen, p->str, sizeof(driver->vncListen));
-        driver->vncListen[sizeof(driver->vncListen)-1] = '\0';
+        if (!(driver->vncListen = strdup(p->str))) {
+            qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY,
+                             "%s", _("failed to allocate vncTLSx509certdir"));
+            virConfFree(conf);
+            return -1;
+        }
     }
 
     virConfFree (conf);
     return 0;
 }
 
-
-struct qemud_vm *qemudFindVMByID(const struct qemud_driver *driver, int id) {
-    struct qemud_vm *vm = driver->vms;
-
-    while (vm) {
-        if (qemudIsActiveVM(vm) && vm->id == id)
-            return vm;
-        vm = vm->next;
-    }
-
-    return NULL;
-}
-
-struct qemud_vm *qemudFindVMByUUID(const struct qemud_driver *driver,
-                                   const unsigned char *uuid) {
-    struct qemud_vm *vm = driver->vms;
-
-    while (vm) {
-        if (!memcmp(vm->def->uuid, uuid, VIR_UUID_BUFLEN))
-            return vm;
-        vm = vm->next;
-    }
-
-    return NULL;
-}
-
-struct qemud_vm *qemudFindVMByName(const struct qemud_driver *driver,
-                                   const char *name) {
-    struct qemud_vm *vm = driver->vms;
-
-    while (vm) {
-        if (STREQ(vm->def->name, name))
-            return vm;
-        vm = vm->next;
-    }
-
-    return NULL;
-}
-
-
-/* Free all memory associated with a struct qemud_vm object */
-void qemudFreeVMDef(struct qemud_vm_def *def) {
-    struct qemud_vm_disk_def *disk = def->disks;
-    struct qemud_vm_net_def *net = def->nets;
-    struct qemud_vm_input_def *input = def->inputs;
-    struct qemud_vm_chr_def *serial = def->serials;
-    struct qemud_vm_chr_def *parallel = def->parallels;
-    struct qemud_vm_sound_def *sound = def->sounds;
-
-    while (disk) {
-        struct qemud_vm_disk_def *prev = disk;
-        disk = disk->next;
-        VIR_FREE(prev);
-    }
-    while (net) {
-        struct qemud_vm_net_def *prev = net;
-        net = net->next;
-        VIR_FREE(prev);
-    }
-    while (input) {
-        struct qemud_vm_input_def *prev = input;
-        input = input->next;
-        VIR_FREE(prev);
-    }
-    while (serial) {
-        struct qemud_vm_chr_def *prev = serial;
-        serial = serial->next;
-        VIR_FREE(prev);
-    }
-    while (parallel) {
-        struct qemud_vm_chr_def *prev = parallel;
-        parallel = parallel->next;
-        VIR_FREE(prev);
-    }
-    while (sound) {
-        struct qemud_vm_sound_def *prev = sound;
-        sound = sound->next;
-        VIR_FREE(prev);
-    }
-    xmlFree(def->keymap);
-    VIR_FREE(def);
-}
-
-void qemudFreeVM(struct qemud_vm *vm) {
-    qemudFreeVMDef(vm->def);
-    if (vm->newDef)
-        qemudFreeVMDef(vm->newDef);
-    VIR_FREE(vm);
-}
-
-
 /* The list of possible machine types for various architectures,
    as supported by QEMU - taken from 'qemu -M ?' for each arch */
 static const char *const arch_info_hvm_x86_machines[] = {
@@ -477,12 +396,14 @@ virCapsPtr qemudCapsInit(void) {
 }
 
 
-static int qemudExtractVersionInfo(const char *qemu, int *version, int *flags) {
+int qemudExtractVersionInfo(const char *qemu, int *version, int *flags) {
     pid_t child;
     int newstdout[2];
 
-    *flags = 0;
-    *version = 0;
+    if (flags)
+        *flags = 0;
+    if (version)
+        *version = 0;
 
     if (pipe(newstdout) < 0) {
         return -1;
@@ -517,6 +438,7 @@ static int qemudExtractVersionInfo(const char *qemu, int *version, int *flags) {
         char help[8192]; /* Ought to be enough to hold QEMU help screen */
         int got = 0, ret = -1;
         int major, minor, micro;
+        int ver;
 
         if (close(newstdout[1]) < 0)
             goto cleanup2;
@@ -538,19 +460,23 @@ static int qemudExtractVersionInfo(const char *qemu, int *version, int *flags) {
             goto cleanup2;
         }
 
-        *version = (major * 1000 * 1000) + (minor * 1000) + micro;
-        if (strstr(help, "-no-kqemu"))
-            *flags |= QEMUD_CMD_FLAG_KQEMU;
-        if (strstr(help, "-no-reboot"))
-            *flags |= QEMUD_CMD_FLAG_NO_REBOOT;
-        if (strstr(help, "-name"))
-            *flags |= QEMUD_CMD_FLAG_NAME;
-        if (strstr(help, "-drive"))
-            *flags |= QEMUD_CMD_FLAG_DRIVE;
-        if (strstr(help, "boot=on"))
-            *flags |= QEMUD_CMD_FLAG_DRIVE_BOOT;
-        if (*version >= 9000)
-            *flags |= QEMUD_CMD_FLAG_VNC_COLON;
+        ver = (major * 1000 * 1000) + (minor * 1000) + micro;
+        if (version)
+            *version = ver;
+        if (flags) {
+            if (strstr(help, "-no-kqemu"))
+                *flags |= QEMUD_CMD_FLAG_KQEMU;
+            if (strstr(help, "-no-reboot"))
+                *flags |= QEMUD_CMD_FLAG_NO_REBOOT;
+            if (strstr(help, "-name"))
+                *flags |= QEMUD_CMD_FLAG_NAME;
+            if (strstr(help, "-drive"))
+                *flags |= QEMUD_CMD_FLAG_DRIVE;
+            if (strstr(help, "boot=on"))
+                *flags |= QEMUD_CMD_FLAG_DRIVE_BOOT;
+            if (ver >= 9000)
+                *flags |= QEMUD_CMD_FLAG_VNC_COLON;
+        }
         ret = 0;
 
         qemudDebug("Version %d %d %d  Cooked version: %d, with flags ? %d",
@@ -594,1681 +520,71 @@ int qemudExtractVersion(virConnectPtr conn,
 
     if ((binary = virCapabilitiesDefaultGuestEmulator(driver->caps,
                                                       "hvm",
-                                                      "i686",
-                                                      "qemu")) == NULL)
-        return -1;
-
-    if (stat(binary, &sb) < 0) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         _("Cannot find QEMU binary %s: %s"), binary,
-                         strerror(errno));
-        return -1;
-    }
-
-    if (qemudExtractVersionInfo(binary, &driver->qemuVersion, &ignored) < 0) {
-        return -1;
-    }
-
-    return 0;
-}
-
-/* Converts def->virtType to applicable string type
- * @param type integer virt type
- * @return string type on success, NULL on fail
- */
-const char * qemudVirtTypeToString(int type) {
-    switch (type) {
-        case QEMUD_VIRT_QEMU:
-            return "qemu";
-        case QEMUD_VIRT_KQEMU:
-            return "kqemu";
-        case QEMUD_VIRT_KVM:
-            return "kvm";
-    }
-    return NULL;
-}
-
-/* Parse the XML definition for a disk
- * @param disk pre-allocated & zero'd disk record
- * @param node XML nodeset to parse for disk definition
- * @return 0 on success, -1 on failure
- */
-static int qemudParseDiskXML(virConnectPtr conn,
-                             struct qemud_vm_disk_def *disk,
-                             xmlNodePtr node) {
-    xmlNodePtr cur;
-    xmlChar *device = NULL;
-    xmlChar *source = NULL;
-    xmlChar *target = NULL;
-    xmlChar *type = NULL;
-    xmlChar *bus = NULL;
-    int typ = 0;
-
-    type = xmlGetProp(node, BAD_CAST "type");
-    if (type != NULL) {
-        if (xmlStrEqual(type, BAD_CAST "file"))
-            typ = QEMUD_DISK_FILE;
-        else if (xmlStrEqual(type, BAD_CAST "block"))
-            typ = QEMUD_DISK_BLOCK;
-        else {
-            typ = QEMUD_DISK_FILE;
-        }
-        xmlFree(type);
-        type = NULL;
-    }
-
-    device = xmlGetProp(node, BAD_CAST "device");
-
-    cur = node->children;
-    while (cur != NULL) {
-        if (cur->type == XML_ELEMENT_NODE) {
-            if ((source == NULL) &&
-                (xmlStrEqual(cur->name, BAD_CAST "source"))) {
-
-                if (typ == QEMUD_DISK_FILE)
-                    source = xmlGetProp(cur, BAD_CAST "file");
-                else
-                    source = xmlGetProp(cur, BAD_CAST "dev");
-            } else if ((target == NULL) &&
-                       (xmlStrEqual(cur->name, BAD_CAST "target"))) {
-                target = xmlGetProp(cur, BAD_CAST "dev");
-                bus = xmlGetProp(cur, BAD_CAST "bus");
-            } else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) {
-                disk->readonly = 1;
-            }
-        }
-        cur = cur->next;
-    }
-
-    if (source == NULL) {
-        /* There is a case without the source
-         * to the CD-ROM device
-         */
-        if (!device || STRNEQ((const char *) device, "cdrom")) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SOURCE,
-                             target ? "%s" : NULL, target);
-            goto error;
-        }
-    }
-
-    if (target == NULL) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_TARGET, source ? "%s" : NULL, source);
-        goto error;
-    }
-
-    if (device &&
-        STREQ((const char *)device, "floppy") &&
-        STRNEQ((const char *)target, "fda") &&
-        STRNEQ((const char *)target, "fdb")) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         _("Invalid floppy device name: %s"), target);
-        goto error;
-    }
-
-    if (device &&
-        STREQ((const char *)device, "cdrom") &&
-        STRNEQ((const char *)target, "hdc")) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         _("Invalid cdrom device name: %s"), target);
-        goto error;
-    }
-
-    if (device &&
-        STREQ((const char *)device, "cdrom"))
-        disk->readonly = 1;
-
-    if ((!device || STREQ((const char *)device, "disk")) &&
-        !STRPREFIX((const char *)target, "hd") &&
-        !STRPREFIX((const char *)target, "sd") &&
-        !STRPREFIX((const char *)target, "vd") &&
-        !STRPREFIX((const char *)target, "xvd")) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         _("Invalid harddisk device name: %s"), target);
-        goto error;
-    }
-
-    strncpy(disk->src, (source ? (const char *) source : "\0"), NAME_MAX-1);
-    disk->src[NAME_MAX-1] = '\0';
-
-    strncpy(disk->dst, (const char *)target, NAME_MAX-1);
-    disk->dst[NAME_MAX-1] = '\0';
-    disk->type = typ;
-
-    if (!device)
-        disk->device = QEMUD_DISK_DISK;
-    else if (STREQ((const char *)device, "disk"))
-        disk->device = QEMUD_DISK_DISK;
-    else if (STREQ((const char *)device, "cdrom"))
-        disk->device = QEMUD_DISK_CDROM;
-    else if (STREQ((const char *)device, "floppy"))
-        disk->device = QEMUD_DISK_FLOPPY;
-    else {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         _("Invalid device type: %s"), device);
-        goto error;
-    }
-
-    if (!bus) {
-        if (disk->device == QEMUD_DISK_FLOPPY) {
-            disk->bus = QEMUD_DISK_BUS_FDC;
-        } else {
-            if (STRPREFIX((const char *)target, "hd"))
-                disk->bus = QEMUD_DISK_BUS_IDE;
-            else if (STRPREFIX((const char *)target, "sd"))
-                disk->bus = QEMUD_DISK_BUS_SCSI;
-            else if (STRPREFIX((const char *)target, "vd"))
-                disk->bus = QEMUD_DISK_BUS_VIRTIO;
-            else if (STRPREFIX((const char *)target, "xvd"))
-                disk->bus = QEMUD_DISK_BUS_XEN;
-            else
-                disk->bus = QEMUD_DISK_BUS_IDE;
-        }
-    } else if (STREQ((const char *)bus, "ide"))
-        disk->bus = QEMUD_DISK_BUS_IDE;
-    else if (STREQ((const char *)bus, "fdc"))
-        disk->bus = QEMUD_DISK_BUS_FDC;
-    else if (STREQ((const char *)bus, "scsi"))
-        disk->bus = QEMUD_DISK_BUS_SCSI;
-    else if (STREQ((const char *)bus, "virtio"))
-        disk->bus = QEMUD_DISK_BUS_VIRTIO;
-    else if (STREQ((const char *)bus, "xen"))
-        disk->bus = QEMUD_DISK_BUS_XEN;
-    else {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         _("Invalid bus type: %s"), bus);
-        goto error;
-    }
-
-    if (disk->device == QEMUD_DISK_FLOPPY &&
-        disk->bus != QEMUD_DISK_BUS_FDC) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         _("Invalid bus type '%s' for floppy disk"), bus);
-        goto error;
-    }
-
-    xmlFree(device);
-    xmlFree(target);
-    xmlFree(source);
-    xmlFree(bus);
-
-    return 0;
-
- error:
-    xmlFree(bus);
-    xmlFree(type);
-    xmlFree(target);
-    xmlFree(source);
-    xmlFree(device);
-    return -1;
-}
-
-static void qemudRandomMAC(struct qemud_vm_net_def *net) {
-    net->mac[0] = 0x52;
-    net->mac[1] = 0x54;
-    net->mac[2] = 0x00;
-    net->mac[3] = 1 + (int)(256*(rand()/(RAND_MAX+1.0)));
-    net->mac[4] = 1 + (int)(256*(rand()/(RAND_MAX+1.0)));
-    net->mac[5] = 1 + (int)(256*(rand()/(RAND_MAX+1.0)));
-}
-
-
-/* Parse the XML definition for a network interface
- * @param net pre-allocated & zero'd net record
- * @param node XML nodeset to parse for net definition
- * @return 0 on success, -1 on failure
- */
-static int qemudParseInterfaceXML(virConnectPtr conn,
-                                  struct qemud_vm_net_def *net,
-                                  xmlNodePtr node) {
-    xmlNodePtr cur;
-    xmlChar *macaddr = NULL;
-    xmlChar *type = NULL;
-    xmlChar *network = NULL;
-    xmlChar *bridge = NULL;
-    xmlChar *ifname = NULL;
-    xmlChar *script = NULL;
-    xmlChar *address = NULL;
-    xmlChar *port = NULL;
-    xmlChar *model = NULL;
-
-    net->type = QEMUD_NET_USER;
-
-    type = xmlGetProp(node, BAD_CAST "type");
-    if (type != NULL) {
-        if (xmlStrEqual(type, BAD_CAST "user"))
-            net->type = QEMUD_NET_USER;
-        else if (xmlStrEqual(type, BAD_CAST "ethernet"))
-            net->type = QEMUD_NET_ETHERNET;
-        else if (xmlStrEqual(type, BAD_CAST "server"))
-            net->type = QEMUD_NET_SERVER;
-        else if (xmlStrEqual(type, BAD_CAST "client"))
-            net->type = QEMUD_NET_CLIENT;
-        else if (xmlStrEqual(type, BAD_CAST "mcast"))
-            net->type = QEMUD_NET_MCAST;
-        else if (xmlStrEqual(type, BAD_CAST "network"))
-            net->type = QEMUD_NET_NETWORK;
-        else if (xmlStrEqual(type, BAD_CAST "bridge"))
-            net->type = QEMUD_NET_BRIDGE;
-        else
-            net->type = QEMUD_NET_USER;
-        xmlFree(type);
-        type = NULL;
-    }
-
-    cur = node->children;
-    while (cur != NULL) {
-        if (cur->type == XML_ELEMENT_NODE) {
-            if ((macaddr == NULL) &&
-                (xmlStrEqual(cur->name, BAD_CAST "mac"))) {
-                macaddr = xmlGetProp(cur, BAD_CAST "address");
-            } else if ((network == NULL) &&
-                       (net->type == QEMUD_NET_NETWORK) &&
-                       (xmlStrEqual(cur->name, BAD_CAST "source"))) {
-                network = xmlGetProp(cur, BAD_CAST "network");
-            } else if ((network == NULL) &&
-                       (net->type == QEMUD_NET_BRIDGE) &&
-                       (xmlStrEqual(cur->name, BAD_CAST "source"))) {
-                bridge = xmlGetProp(cur, BAD_CAST "bridge");
-            } else if ((network == NULL) &&
-                       ((net->type == QEMUD_NET_SERVER) ||
-                        (net->type == QEMUD_NET_CLIENT) ||
-                        (net->type == QEMUD_NET_MCAST)) &&
-                       (xmlStrEqual(cur->name, BAD_CAST "source"))) {
-                address = xmlGetProp(cur, BAD_CAST "address");
-                port = xmlGetProp(cur, BAD_CAST "port");
-            } else if ((ifname == NULL) &&
-                       ((net->type == QEMUD_NET_NETWORK) ||
-                        (net->type == QEMUD_NET_ETHERNET) ||
-                        (net->type == QEMUD_NET_BRIDGE)) &&
-                       xmlStrEqual(cur->name, BAD_CAST "target")) {
-                ifname = xmlGetProp(cur, BAD_CAST "dev");
-                if (STRPREFIX((const char*)ifname, "vnet")) {
-                    /* An auto-generated target name, blank it out */
-                    xmlFree(ifname);
-                    ifname = NULL;
-                }
-            } else if ((script == NULL) &&
-                       (net->type == QEMUD_NET_ETHERNET) &&
-                       xmlStrEqual(cur->name, BAD_CAST "script")) {
-                script = xmlGetProp(cur, BAD_CAST "path");
-            } else if (xmlStrEqual (cur->name, BAD_CAST "model")) {
-                model = xmlGetProp (cur, BAD_CAST "type");
-            }
-        }
-        cur = cur->next;
-    }
-
-    if (macaddr) {
-        unsigned int mac[6];
-        sscanf((const char *)macaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
-               (unsigned int*)&mac[0],
-               (unsigned int*)&mac[1],
-               (unsigned int*)&mac[2],
-               (unsigned int*)&mac[3],
-               (unsigned int*)&mac[4],
-               (unsigned int*)&mac[5]);
-        net->mac[0] = mac[0];
-        net->mac[1] = mac[1];
-        net->mac[2] = mac[2];
-        net->mac[3] = mac[3];
-        net->mac[4] = mac[4];
-        net->mac[5] = mac[5];
-
-        xmlFree(macaddr);
-        macaddr = NULL;
-    } else {
-        qemudRandomMAC(net);
-    }
-
-    if (net->type == QEMUD_NET_NETWORK) {
-        int len;
-
-        if (network == NULL) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("No <source> 'network' attribute specified with <interface type='network'/>"));
-            goto error;
-        } else if ((len = xmlStrlen(network)) >= (QEMUD_MAX_NAME_LEN-1)) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             _("Network name '%s' too long"), network);
-            goto error;
-        } else {
-            strncpy(net->dst.network.name, (char *)network, len);
-            net->dst.network.name[len] = '\0';
-        }
-
-        if (network) {
-            xmlFree(network);
-            network = NULL;
-        }
-
-        if (ifname != NULL) {
-            if ((len = xmlStrlen(ifname)) >= (BR_IFNAME_MAXLEN-1)) {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                                 _("TAP interface name '%s' is too long"),
-                                 ifname);
-                goto error;
-            } else {
-                strncpy(net->dst.network.ifname, (char *)ifname, len);
-                net->dst.network.ifname[len] = '\0';
-            }
-            xmlFree(ifname);
-            ifname = NULL;
-        }
-    } else if (net->type == QEMUD_NET_ETHERNET) {
-        int len;
-
-        if (script != NULL) {
-            if ((len = xmlStrlen(script)) >= (PATH_MAX-1)) {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                                 _("TAP script path '%s' is too long"), script);
-                goto error;
-            } else {
-                strncpy(net->dst.ethernet.script, (char *)script, len);
-                net->dst.ethernet.script[len] = '\0';
-            }
-            xmlFree(script);
-            script = NULL;
-        }
-        if (ifname != NULL) {
-            if ((len = xmlStrlen(ifname)) >= (BR_IFNAME_MAXLEN-1)) {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                                 _("TAP interface name '%s' is too long"),
-                                 ifname);
-                goto error;
-            } else {
-                strncpy(net->dst.ethernet.ifname, (char *)ifname, len);
-                net->dst.ethernet.ifname[len] = '\0';
-            }
-            xmlFree(ifname);
-        }
-    } else if (net->type == QEMUD_NET_BRIDGE) {
-        int len;
-
-        if (bridge == NULL) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("No <source> 'dev' attribute specified with <interface type='bridge'/>"));
-            goto error;
-        } else if ((len = xmlStrlen(bridge)) >= (BR_IFNAME_MAXLEN-1)) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             _("TAP bridge path '%s' is too long"), bridge);
-            goto error;
-        } else {
-            strncpy(net->dst.bridge.brname, (char *)bridge, len);
-            net->dst.bridge.brname[len] = '\0';
-        }
-
-        xmlFree(bridge);
-        bridge = NULL;
-
-        if (ifname != NULL) {
-            if ((len = xmlStrlen(ifname)) >= (BR_IFNAME_MAXLEN-1)) {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                                 _("TAP interface name '%s' is too long"), ifname);
-                goto error;
-            } else {
-                strncpy(net->dst.bridge.ifname, (char *)ifname, len);
-                net->dst.bridge.ifname[len] = '\0';
-            }
-            xmlFree(ifname);
-        }
-    } else if (net->type == QEMUD_NET_CLIENT ||
-               net->type == QEMUD_NET_SERVER ||
-               net->type == QEMUD_NET_MCAST) {
-        int len = 0;
-        char *ret;
-
-        if (port == NULL) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("No <source> 'port' attribute specified with socket interface"));
-            goto error;
-        }
-        if (!(net->dst.socket.port = strtol((char*)port, &ret, 10)) &&
-            ret == (char*)port) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("Cannot parse <source> 'port' attribute with socket interface"));
-            goto error;
-        }
-        xmlFree(port);
-        port = NULL;
-
-        if (address == NULL) {
-            if (net->type == QEMUD_NET_CLIENT ||
-                net->type == QEMUD_NET_MCAST) {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                                 "%s", _("No <source> 'address' attribute specified with socket interface"));
-                goto error;
-            }
-        } else if ((len = xmlStrlen(address)) >= (BR_INET_ADDR_MAXLEN)) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             _("IP address '%s' is too long"), address);
-            goto error;
-        }
-        if (address == NULL) {
-            net->dst.socket.address[0] = '\0';
-        } else {
-            strncpy(net->dst.socket.address, (char*)address,len);
-            net->dst.socket.address[len] = '\0';
-        }
-        xmlFree(address);
-    }
-
-    /* NIC model (see -net nic,model=?).  We only check that it looks
-     * reasonable, not that it is a supported NIC type.  FWIW kvm
-     * supports these types as of April 2008:
-     * i82551 i82557b i82559er ne2k_pci pcnet rtl8139 e1000 virtio
-     */
-    if (model != NULL) {
-        int i, len;
-
-        len = xmlStrlen (model);
-        if (len >= QEMUD_MODEL_MAX_LEN) {
-            qemudReportError (conn, NULL, NULL, VIR_ERR_INVALID_ARG,
-                              _("Model name '%s' is too long"), model);
-            goto error;
-        }
-        for (i = 0; i < len; ++i) {
-            int char_ok = c_isalnum(model[i]) || model[i] == '_';
-            if (!char_ok) {
-                qemudReportError (conn, NULL, NULL, VIR_ERR_INVALID_ARG, "%s",
-                                  _("Model name contains invalid characters"));
-                goto error;
-            }
-        }
-        strncpy (net->model, (const char*) model, len);
-        net->model[len] = '\0';
-
-        xmlFree (model);
-        model = NULL;
-    } else
-        net->model[0] = '\0';
-
-    return 0;
-
- error:
-    xmlFree(network);
-    xmlFree(address);
-    xmlFree(port);
-    xmlFree(ifname);
-    xmlFree(script);
-    xmlFree(bridge);
-    xmlFree(model);
-    return -1;
-}
-
-
-/* Parse the XML definition for a character device
- * @param net pre-allocated & zero'd net record
- * @param node XML nodeset to parse for net definition
- * @return 0 on success, -1 on failure
- *
- * The XML we're dealing with looks like
- *
- * <serial type="pty">
- *   <source path="/dev/pts/3"/>
- *   <target port="1"/>
- * </serial>
- *
- * <serial type="dev">
- *   <source path="/dev/ttyS0"/>
- *   <target port="1"/>
- * </serial>
- *
- * <serial type="tcp">
- *   <source mode="connect" host="0.0.0.0" service="2445"/>
- *   <target port="1"/>
- * </serial>
- *
- * <serial type="tcp">
- *   <source mode="bind" host="0.0.0.0" service="2445"/>
- *   <target port="1"/>
- * </serial>
- *
- * <serial type="udp">
- *   <source mode="bind" host="0.0.0.0" service="2445"/>
- *   <source mode="connect" host="0.0.0.0" service="2445"/>
- *   <target port="1"/>
- * </serial>
- *
- * <serial type="unix">
- *   <source mode="bind" path="/tmp/foo"/>
- *   <target port="1"/>
- * </serial>
- *
- */
-static int qemudParseCharXML(virConnectPtr conn,
-                             struct qemud_vm_chr_def *chr,
-                             int portNum,
-                             xmlNodePtr node) {
-    xmlNodePtr cur;
-    xmlChar *type = NULL;
-    xmlChar *bindHost = NULL;
-    xmlChar *bindService = NULL;
-    xmlChar *connectHost = NULL;
-    xmlChar *connectService = NULL;
-    xmlChar *path = NULL;
-    xmlChar *mode = NULL;
-    xmlChar *protocol = NULL;
-    int ret = -1;
-
-    chr->srcType = QEMUD_CHR_SRC_TYPE_PTY;
-    type = xmlGetProp(node, BAD_CAST "type");
-    if (type != NULL) {
-        if (xmlStrEqual(type, BAD_CAST "null"))
-            chr->srcType = QEMUD_CHR_SRC_TYPE_NULL;
-        else if (xmlStrEqual(type, BAD_CAST "vc"))
-            chr->srcType = QEMUD_CHR_SRC_TYPE_VC;
-        else if (xmlStrEqual(type, BAD_CAST "pty"))
-            chr->srcType = QEMUD_CHR_SRC_TYPE_PTY;
-        else if (xmlStrEqual(type, BAD_CAST "dev"))
-            chr->srcType = QEMUD_CHR_SRC_TYPE_DEV;
-        else if (xmlStrEqual(type, BAD_CAST "file"))
-            chr->srcType = QEMUD_CHR_SRC_TYPE_FILE;
-        else if (xmlStrEqual(type, BAD_CAST "pipe"))
-            chr->srcType = QEMUD_CHR_SRC_TYPE_PIPE;
-        else if (xmlStrEqual(type, BAD_CAST "stdio"))
-            chr->srcType = QEMUD_CHR_SRC_TYPE_STDIO;
-        else if (xmlStrEqual(type, BAD_CAST "udp"))
-            chr->srcType = QEMUD_CHR_SRC_TYPE_UDP;
-        else if (xmlStrEqual(type, BAD_CAST "tcp"))
-            chr->srcType = QEMUD_CHR_SRC_TYPE_TCP;
-        else if (xmlStrEqual(type, BAD_CAST "unix"))
-            chr->srcType = QEMUD_CHR_SRC_TYPE_UNIX;
-        else
-            chr->srcType = QEMUD_CHR_SRC_TYPE_NULL;
-    }
-
-    cur = node->children;
-    while (cur != NULL) {
-        if (cur->type == XML_ELEMENT_NODE) {
-            if (xmlStrEqual(cur->name, BAD_CAST "source")) {
-                if (mode == NULL)
-                    mode = xmlGetProp(cur, BAD_CAST "mode");
-
-                switch (chr->srcType) {
-                case QEMUD_CHR_SRC_TYPE_PTY:
-                case QEMUD_CHR_SRC_TYPE_DEV:
-                case QEMUD_CHR_SRC_TYPE_FILE:
-                case QEMUD_CHR_SRC_TYPE_PIPE:
-                case QEMUD_CHR_SRC_TYPE_UNIX:
-                    if (path == NULL)
-                        path = xmlGetProp(cur, BAD_CAST "path");
-
-                    break;
-
-                case QEMUD_CHR_SRC_TYPE_UDP:
-                case QEMUD_CHR_SRC_TYPE_TCP:
-                    if (mode == NULL ||
-                        STREQ((const char *)mode, "connect")) {
-
-                        if (connectHost == NULL)
-                            connectHost = xmlGetProp(cur, BAD_CAST "host");
-                        if (connectService == NULL)
-                            connectService = xmlGetProp(cur, BAD_CAST "service");
-                    } else {
-                        if (bindHost == NULL)
-                            bindHost = xmlGetProp(cur, BAD_CAST "host");
-                        if (bindService == NULL)
-                            bindService = xmlGetProp(cur, BAD_CAST "service");
-                    }
-
-                    if (chr->srcType == QEMUD_CHR_SRC_TYPE_UDP) {
-                        xmlFree(mode);
-                        mode = NULL;
-                    }
-                }
-            } else if (xmlStrEqual(cur->name, BAD_CAST "protocol")) {
-                if (protocol == NULL)
-                    protocol = xmlGetProp(cur, BAD_CAST "type");
-            }
-        }
-        cur = cur->next;
-    }
-
-
-    chr->dstPort = portNum;
-
-    switch (chr->srcType) {
-    case QEMUD_CHR_SRC_TYPE_NULL:
-        /* Nada */
-        break;
-
-    case QEMUD_CHR_SRC_TYPE_VC:
-        break;
-
-    case QEMUD_CHR_SRC_TYPE_PTY:
-        /* @path attribute is an output only property - pty is auto-allocted */
-        break;
-
-    case QEMUD_CHR_SRC_TYPE_DEV:
-    case QEMUD_CHR_SRC_TYPE_FILE:
-    case QEMUD_CHR_SRC_TYPE_PIPE:
-        if (path == NULL) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("Missing source path attribute for char device"));
-            goto cleanup;
-        }
-
-        strncpy(chr->srcData.file.path, (const char *)path,
-                sizeof(chr->srcData.file.path));
-        NUL_TERMINATE(chr->srcData.file.path);
-        break;
-
-    case QEMUD_CHR_SRC_TYPE_STDIO:
-        /* Nada */
-        break;
-
-    case QEMUD_CHR_SRC_TYPE_TCP:
-        if (mode == NULL ||
-            STREQ((const char *)mode, "connect")) {
-            if (connectHost == NULL) {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                                 "%s", _("Missing source host attribute for char device"));
-                goto cleanup;
-            }
-            if (connectService == NULL) {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                                 "%s", _("Missing source service attribute for char device"));
-                goto cleanup;
-            }
-
-            strncpy(chr->srcData.tcp.host, (const char *)connectHost,
-                    sizeof(chr->srcData.tcp.host));
-            NUL_TERMINATE(chr->srcData.tcp.host);
-            strncpy(chr->srcData.tcp.service, (const char *)connectService,
-                    sizeof(chr->srcData.tcp.service));
-            NUL_TERMINATE(chr->srcData.tcp.service);
-
-            chr->srcData.tcp.listen = 0;
-        } else {
-            if (bindHost == NULL) {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                                 "%s", _("Missing source host attribute for char device"));
-                goto cleanup;
-            }
-            if (bindService == NULL) {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                                 "%s", _("Missing source service attribute for char device"));
-                goto cleanup;
-            }
-
-            strncpy(chr->srcData.tcp.host, (const char *)bindHost,
-                    sizeof(chr->srcData.tcp.host));
-            NUL_TERMINATE(chr->srcData.tcp.host);
-            strncpy(chr->srcData.tcp.service, (const char *)bindService,
-                    sizeof(chr->srcData.tcp.service));
-            NUL_TERMINATE(chr->srcData.tcp.service);
-
-            chr->srcData.tcp.listen = 1;
-        }
-        if (protocol != NULL &&
-            STREQ((const char *)protocol, "telnet"))
-            chr->srcData.tcp.protocol = QEMUD_CHR_SRC_TCP_PROTOCOL_TELNET;
-        else
-            chr->srcData.tcp.protocol = QEMUD_CHR_SRC_TCP_PROTOCOL_RAW;
-        break;
-
-    case QEMUD_CHR_SRC_TYPE_UDP:
-        if (connectService == NULL) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("Missing source service attribute for char device"));
-            goto cleanup;
-        }
-
-        if (connectHost != NULL) {
-            strncpy(chr->srcData.udp.connectHost, (const char *)connectHost,
-                    sizeof(chr->srcData.udp.connectHost));
-            NUL_TERMINATE(chr->srcData.udp.connectHost);
-        }
-        strncpy(chr->srcData.udp.connectService, (const char *)connectService,
-                sizeof(chr->srcData.udp.connectService));
-        NUL_TERMINATE(chr->srcData.udp.connectService);
-
-        if (bindHost != NULL) {
-            strncpy(chr->srcData.udp.bindHost, (const char *)bindHost,
-                    sizeof(chr->srcData.udp.bindHost));
-            NUL_TERMINATE(chr->srcData.udp.bindHost);
-        }
-        if (bindService != NULL) {
-            strncpy(chr->srcData.udp.bindService, (const char *)bindService,
-                    sizeof(chr->srcData.udp.bindService));
-            NUL_TERMINATE(chr->srcData.udp.bindService);
-        }
-        break;
-
-    case QEMUD_CHR_SRC_TYPE_UNIX:
-        if (path == NULL) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("Missing source path attribute for char device"));
-            goto cleanup;
-        }
-
-        if (mode != NULL &&
-            STRNEQ((const char *)mode, "connect"))
-            chr->srcData.nix.listen = 1;
-        else
-            chr->srcData.nix.listen = 0;
-
-        strncpy(chr->srcData.nix.path, (const char *)path,
-                sizeof(chr->srcData.nix.path));
-        NUL_TERMINATE(chr->srcData.nix.path);
-        break;
-    }
-
-    ret = 0;
-
-cleanup:
-    xmlFree(mode);
-    xmlFree(protocol);
-    xmlFree(type);
-    xmlFree(bindHost);
-    xmlFree(bindService);
-    xmlFree(connectHost);
-    xmlFree(connectService);
-    xmlFree(path);
-
-    return ret;
-}
-
-
-static int qemudParseCharXMLDevices(virConnectPtr conn,
-                                    xmlXPathContextPtr ctxt,
-                                    const char *xpath,
-                                    unsigned int *ndevs,
-                                    struct qemud_vm_chr_def **devs)
-{
-    xmlXPathObjectPtr obj;
-    int i, ret = -1;
-
-    obj = xmlXPathEval(BAD_CAST xpath, ctxt);
-    if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
-        (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
-        struct qemud_vm_chr_def *prev = *devs;
-        if (ndevs == NULL &&
-            obj->nodesetval->nodeNr > 1) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("too many character devices"));
-            goto cleanup;
-        }
-
-        for (i = 0; i < obj->nodesetval->nodeNr; i++) {
-            struct qemud_vm_chr_def *chr;
-            if (VIR_ALLOC(chr) < 0) {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
-                                 "%s",
-                                 _("failed to allocate space for char device"));
-                goto cleanup;
-            }
-
-            if (qemudParseCharXML(conn, chr, i, obj->nodesetval->nodeTab[i]) < 0) {
-                VIR_FREE(chr);
-                goto cleanup;
-            }
-            if (ndevs)
-                (*ndevs)++;
-            chr->next = NULL;
-            if (i == 0) {
-                *devs = chr;
-            } else {
-                prev->next = chr;
-            }
-            prev = chr;
-        }
-    }
-
-    ret = 0;
-
-cleanup:
-    xmlXPathFreeObject(obj);
-    return ret;
-}
-
-
-/* Parse the XML definition for a network interface */
-static int qemudParseInputXML(virConnectPtr conn,
-                              const struct qemud_vm_def *vm,
-                              struct qemud_vm_input_def *input,
-                              xmlNodePtr node) {
-    xmlChar *type = NULL;
-    xmlChar *bus = NULL;
-
-    type = xmlGetProp(node, BAD_CAST "type");
-    bus = xmlGetProp(node, BAD_CAST "bus");
-
-    if (!type) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("missing input device type"));
-        goto error;
-    }
-
-    if (STREQ((const char *)type, "mouse")) {
-        input->type = QEMU_INPUT_TYPE_MOUSE;
-    } else if (STREQ((const char *)type, "tablet")) {
-        input->type = QEMU_INPUT_TYPE_TABLET;
-    } else {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         _("unsupported input device type %s"),
-                         (const char*)type);
-        goto error;
-    }
-
-    if (bus) {
-        if (STREQ(vm->os.type, "hvm")) {
-            if (STREQ((const char*)bus, "ps2")) { /* Only allow mouse */
-                if (input->type != QEMU_INPUT_TYPE_MOUSE) {
-                    qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                                     _("ps2 bus does not support %s input device"),
-                                     (const char*)type);
-                    goto error;
-                }
-                input->bus = QEMU_INPUT_BUS_PS2;
-            } else if (STREQ((const char *)bus, "usb")) { /* Allow mouse & tablet */
-                input->bus = QEMU_INPUT_BUS_USB;
-            } else {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                                 _("unsupported input bus %s"), (const char*)bus);
-                goto error;
-            }
-        } else {
-            if (STREQ((const char *)bus, "xen")) { /* Allow mouse only */
-                input->bus = QEMU_INPUT_BUS_XEN;
-                if (input->type != QEMU_INPUT_TYPE_MOUSE) {
-                    qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                                     _("xen bus does not support %s input device"),
-                                     (const char*)type);
-                    goto error;
-                }
-            } else {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                                 _("unsupported input bus %s"), (const char*)bus);
-                goto error;
-            }
-        }
-    } else {
-        if (STREQ(vm->os.type, "hvm")) {
-            if (input->type == QEMU_INPUT_TYPE_MOUSE)
-                input->bus = QEMU_INPUT_BUS_PS2;
-            else
-                input->bus = QEMU_INPUT_BUS_USB;
-        } else {
-            input->bus = QEMU_INPUT_BUS_XEN;
-        }
-    }
-
-    xmlFree(type);
-    xmlFree(bus);
-
-    return 0;
-
- error:
-    xmlFree(type);
-    xmlFree(bus);
-
-    return -1;
-}
-
-static int qemudDiskCompare(const void *aptr, const void *bptr) {
-    struct qemud_vm_disk_def *a = (struct qemud_vm_disk_def *) aptr;
-    struct qemud_vm_disk_def *b = (struct qemud_vm_disk_def *) bptr;
-    if (a->bus == b->bus)
-        return virDiskNameToIndex(a->dst) - virDiskNameToIndex(b->dst);
-    else
-        return a->bus - b->bus;
-}
-
-static const char *qemudBusIdToName(int busId, int qemuIF) {
-    const char *busnames[] = { "ide",
-                               (qemuIF ? "floppy" : "fdc"),
-                               "scsi",
-                               "virtio",
-                               "xen"};
-    verify_true(ARRAY_CARDINALITY(busnames) == QEMUD_DISK_BUS_LAST);
-
-    return busnames[busId];
-}
-
-/* Sound device helper functions */
-static int qemudSoundModelFromString(const char *model) {
-    if (STREQ(model, "sb16")) {
-        return QEMU_SOUND_SB16;
-    } else if (STREQ(model, "es1370")) {
-        return QEMU_SOUND_ES1370;
-    } else if (STREQ(model, "pcspk")) {
-        return QEMU_SOUND_PCSPK;
-    }
-
-    return -1;
-}
-
-static const char *qemudSoundModelToString(const int model) {
-
-    if (model == QEMU_SOUND_SB16) {
-        return "sb16";
-    } else if (model == QEMU_SOUND_ES1370) {
-        return "es1370";
-    } else if (model == QEMU_SOUND_PCSPK) {
-        return "pcspk";
-    }
-
-    return NULL;
-}
-
-
-static int qemudParseSoundXML(virConnectPtr conn,
-                              struct qemud_vm_sound_def *sound,
-                              const xmlNodePtr node) {
-
-    int err = -1;
-    xmlChar *model = NULL;
-    model = xmlGetProp(node, BAD_CAST "model");
-
-    if (!model) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("missing sound model"));
-        goto error;
-    }
-    if ((sound->model = qemudSoundModelFromString((char *) model)) < 0) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         _("invalid sound model '%s'"), (char *) model);
-        goto error;
-    }
-
-    err = 0;
- error:
-    xmlFree(model);
-    return err;
-}
-
-/*
- * Parses a libvirt XML definition of a guest, and populates the
- * the qemud_vm struct with matching data about the guests config
- */
-static struct qemud_vm_def *qemudParseXML(virConnectPtr conn,
-                                          struct qemud_driver *driver,
-                                          xmlDocPtr xml) {
-    xmlNodePtr root = NULL;
-    xmlChar *prop = NULL;
-    xmlXPathContextPtr ctxt = NULL;
-    xmlXPathObjectPtr obj = NULL;
-    char *conv = NULL;
-    int i;
-    struct qemud_vm_def *def;
-
-    if (VIR_ALLOC(def) < 0) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
-                         "%s", _("failed to allocate space for xmlXPathContext"));
-        return NULL;
-    }
-
-    /* Prepare parser / xpath context */
-    root = xmlDocGetRootElement(xml);
-    if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "domain"))) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("incorrect root element"));
-        goto error;
-    }
-
-    ctxt = xmlXPathNewContext(xml);
-    if (ctxt == NULL) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
-                         "%s", _("failed to allocate space for xmlXPathContext"));
-        goto error;
-    }
-
-
-    /* Find out what type of QEMU virtualization to use */
-    if (!(prop = xmlGetProp(root, BAD_CAST "type"))) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("missing domain type attribute"));
-        goto error;
-    }
-
-    if (STREQ((char *)prop, "qemu"))
-        def->virtType = QEMUD_VIRT_QEMU;
-    else if (STREQ((char *)prop, "kqemu"))
-        def->virtType = QEMUD_VIRT_KQEMU;
-    else if (STREQ((char *)prop, "kvm"))
-        def->virtType = QEMUD_VIRT_KVM;
-    else {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("invalid domain type attribute"));
-        goto error;
-    }
-    VIR_FREE(prop);
-
-
-    /* Extract domain name */
-    obj = xmlXPathEval(BAD_CAST "string(/domain/name[1])", ctxt);
-    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_NAME, NULL);
-        goto error;
-    }
-    if (strlen((const char *)obj->stringval) >= (QEMUD_MAX_NAME_LEN-1)) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("domain name length too long"));
-        goto error;
-    }
-    strcpy(def->name, (const char *)obj->stringval);
-    xmlXPathFreeObject(obj);
-
-
-    /* Extract domain uuid */
-    obj = xmlXPathEval(BAD_CAST "string(/domain/uuid[1])", ctxt);
-    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-        int err;
-        if ((err = virUUIDGenerate(def->uuid))) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             _("Failed to generate UUID: %s"), strerror(err));
-            goto error;
-        }
-    } else if (virUUIDParse((const char *)obj->stringval, def->uuid) < 0) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("malformed uuid element"));
-        goto error;
-    }
-    xmlXPathFreeObject(obj);
-
-
-    /* Extract domain memory */
-    obj = xmlXPathEval(BAD_CAST "string(/domain/memory[1])", ctxt);
-    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("missing memory element"));
-        goto error;
-    } else {
-        conv = NULL;
-        def->maxmem = strtoll((const char*)obj->stringval, &conv, 10);
-        if (conv == (const char*)obj->stringval) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("malformed memory information"));
-            goto error;
-        }
-    }
-    xmlXPathFreeObject(obj);
-
-
-    /* Extract domain memory */
-    obj = xmlXPathEval(BAD_CAST "string(/domain/currentMemory[1])", ctxt);
-    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-        def->memory = def->maxmem;
-    } else {
-        conv = NULL;
-        def->memory = strtoll((const char*)obj->stringval, &conv, 10);
-        if (def->memory > def->maxmem)
-            def->memory = def->maxmem;
-        if (conv == (const char*)obj->stringval) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("malformed memory information"));
-            goto error;
-        }
-    }
-    xmlXPathFreeObject(obj);
-
-    /* Extract domain vcpu info */
-    obj = xmlXPathEval(BAD_CAST "string(/domain/vcpu[1])", ctxt);
-    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-        def->vcpus = 1;
-    } else {
-        conv = NULL;
-        def->vcpus = strtoll((const char*)obj->stringval, &conv, 10);
-        if (conv == (const char*)obj->stringval) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("malformed vcpu information"));
-            goto error;
-        }
-    }
-    xmlXPathFreeObject(obj);
-
-    /* Extract domain vcpu info */
-    obj = xmlXPathEval(BAD_CAST "string(/domain/vcpu[1]/@cpuset)", ctxt);
-    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-        /* Allow use on all CPUS */
-        memset(def->cpumask, 1, QEMUD_CPUMASK_LEN);
-    } else {
-        char *set = (char *)obj->stringval;
-        memset(def->cpumask, 0, QEMUD_CPUMASK_LEN);
-        if (virParseCpuSet(conn, (const char **)&set,
-                           0, def->cpumask,
-                           QEMUD_CPUMASK_LEN) < 0) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("malformed vcpu mask information"));
-            goto error;
-        }
-    }
-    xmlXPathFreeObject(obj);
-
-    /* See if ACPI feature is requested */
-    obj = xmlXPathEval(BAD_CAST "/domain/features/acpi", ctxt);
-    if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
-        (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
-        def->features |= QEMUD_FEATURE_ACPI;
-    }
-    xmlXPathFreeObject(obj);
-
-
-    /* See if we disable reboots */
-    obj = xmlXPathEval(BAD_CAST "string(/domain/on_reboot)", ctxt);
-    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-        def->noReboot = 0;
-    } else {
-        if (STREQ((char*)obj->stringval, "destroy"))
-            def->noReboot = 1;
-        else
-            def->noReboot = 0;
-    }
-    xmlXPathFreeObject(obj);
-
-    /* See if we set clock to localtime */
-    obj = xmlXPathEval(BAD_CAST "string(/domain/clock/@offset)", ctxt);
-    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-        def->localtime = 0;
-    } else {
-        if (STREQ((char*)obj->stringval, "localtime"))
-            def->localtime = 1;
-        else
-            def->localtime = 0;
-    }
-    xmlXPathFreeObject(obj);
-
-
-    /* Extract bootloader */
-    obj = xmlXPathEval(BAD_CAST "string(/domain/bootloader)", ctxt);
-    if ((obj != NULL) && (obj->type == XPATH_STRING) &&
-        (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
-        strncpy(def->os.bootloader, (const char*)obj->stringval, sizeof(def->os.bootloader));
-        NUL_TERMINATE(def->os.bootloader);
-
-        /* Set a default OS type, since <type> is optional with bootloader */
-        strcpy(def->os.type, "xen");
-    }
-    xmlXPathFreeObject(obj);
-
-    /* Extract OS type info */
-    obj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1])", ctxt);
-    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-        if (!def->os.type[0]) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_OS_TYPE,
-                             "%s", _("no OS type"));
-            goto error;
-        }
-    } else {
-        strcpy(def->os.type, (const char *)obj->stringval);
-    }
-    xmlXPathFreeObject(obj);
-    obj = NULL;
-
-    if (!virCapabilitiesSupportsGuestOSType(driver->caps, def->os.type)) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_OS_TYPE,
-                         "%s", def->os.type);
-        goto error;
-    }
-
-    obj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1]/@arch)", ctxt);
-    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-        const char *defaultArch = virCapabilitiesDefaultGuestArch(driver->caps, def->os.type);
-        if (defaultArch == NULL) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("unsupported architecture"));
-            goto error;
-        }
-        if (strlen(defaultArch) >= (QEMUD_OS_TYPE_MAX_LEN-1)) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("architecture type too long"));
-            goto error;
-        }
-        strcpy(def->os.arch, defaultArch);
-    } else {
-        if (strlen((const char *)obj->stringval) >= (QEMUD_OS_TYPE_MAX_LEN-1)) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("architecture type too long"));
-            goto error;
-        }
-        strcpy(def->os.arch, (const char *)obj->stringval);
-    }
-    xmlXPathFreeObject(obj);
-
-    obj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1]/@machine)", ctxt);
-    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-        const char *defaultMachine = virCapabilitiesDefaultGuestMachine(driver->caps,
-                                                                        def->os.type,
-                                                                        def->os.arch);
-        if (defaultMachine == NULL) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("unsupported architecture"));
-            goto error;
-        }
-        if (strlen(defaultMachine) >= (QEMUD_OS_MACHINE_MAX_LEN-1)) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("machine type too long"));
-            goto error;
-        }
-        strcpy(def->os.machine, defaultMachine);
-    } else {
-        if (strlen((const char *)obj->stringval) >= (QEMUD_OS_MACHINE_MAX_LEN-1)) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("architecture type too long"));
-            goto error;
-        }
-        strcpy(def->os.machine, (const char *)obj->stringval);
-    }
-    xmlXPathFreeObject(obj);
-
-
-    if (!def->os.bootloader[0]) {
-        obj = xmlXPathEval(BAD_CAST "string(/domain/os/kernel[1])", ctxt);
-        if ((obj != NULL) && (obj->type == XPATH_STRING) &&
-            (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
-            if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                                 "%s", _("kernel path too long"));
-                goto error;
-            }
-            strcpy(def->os.kernel, (const char *)obj->stringval);
-        }
-        xmlXPathFreeObject(obj);
-
-
-        obj = xmlXPathEval(BAD_CAST "string(/domain/os/initrd[1])", ctxt);
-        if ((obj != NULL) && (obj->type == XPATH_STRING) &&
-            (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
-            if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                                 "%s", _("initrd path too long"));
-                goto error;
-            }
-            strcpy(def->os.initrd, (const char *)obj->stringval);
-        }
-        xmlXPathFreeObject(obj);
-
-
-        obj = xmlXPathEval(BAD_CAST "string(/domain/os/cmdline[1])", ctxt);
-        if ((obj != NULL) && (obj->type == XPATH_STRING) &&
-            (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
-            if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                                 "%s", _("cmdline arguments too long"));
-                goto error;
-            }
-            strcpy(def->os.cmdline, (const char *)obj->stringval);
-        }
-        xmlXPathFreeObject(obj);
-
-
-        /* analysis of the disk devices */
-        obj = xmlXPathEval(BAD_CAST "/domain/os/boot", ctxt);
-        if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
-            (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
-            for (i = 0; i < obj->nodesetval->nodeNr && i < QEMUD_MAX_BOOT_DEVS ; i++) {
-                if (!(prop = xmlGetProp(obj->nodesetval->nodeTab[i], BAD_CAST "dev")))
-                    continue;
-                if (STREQ((char *)prop, "hd")) {
-                    def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_DISK;
-                } else if (STREQ((char *)prop, "fd")) {
-                    def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_FLOPPY;
-                } else if (STREQ((char *)prop, "cdrom")) {
-                    def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_CDROM;
-                } else if (STREQ((char *)prop, "network")) {
-                    def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_NET;
-                } else {
-                    qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                                     _("unknown boot device \'%s\'"), (char*)prop);
-                    goto error;
-                }
-                xmlFree(prop);
-                prop = NULL;
-            }
-        }
-        xmlXPathFreeObject(obj);
-        if (def->os.nBootDevs == 0) {
-            def->os.nBootDevs = 1;
-            def->os.bootDevs[0] = QEMUD_BOOT_DISK;
-        }
-    }
-
-    obj = xmlXPathEval(BAD_CAST "string(/domain/devices/emulator[1])", ctxt);
-    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-        const char *type = qemudVirtTypeToString(def->virtType);
-        if (!type) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("unknown virt type"));
-            goto error;
-        }
-        const char *emulator = virCapabilitiesDefaultGuestEmulator(driver->caps,
-                                                                   def->os.type,
-                                                                   def->os.arch,
-                                                                   type);
-        if (!emulator) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("unsupported guest type"));
-            goto error;
-        }
-        strcpy(def->os.binary, emulator);
-    } else {
-        if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("emulator path too long"));
-            goto error;
-        }
-        strcpy(def->os.binary, (const char *)obj->stringval);
-    }
-    xmlXPathFreeObject(obj);
-
-    obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics", ctxt);
-    if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
-        (obj->nodesetval == NULL) || (obj->nodesetval->nodeNr == 0)) {
-        def->graphicsType = QEMUD_GRAPHICS_NONE;
-    } else if ((prop = xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "type"))) {
-        if (STREQ((char *)prop, "vnc")) {
-            xmlChar *vncport, *vnclisten;
-            def->graphicsType = QEMUD_GRAPHICS_VNC;
-            vncport = xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "port");
-            if (vncport) {
-                conv = NULL;
-                def->vncPort = strtoll((const char*)vncport, &conv, 10);
-            } else {
-                def->vncPort = -1;
-            }
-            vnclisten = xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "listen");
-            if (vnclisten && *vnclisten)
-                strncpy(def->vncListen, (char *)vnclisten, BR_INET_ADDR_MAXLEN-1);
-            else
-                strcpy(def->vncListen, driver->vncListen);
-            def->vncListen[BR_INET_ADDR_MAXLEN-1] = '\0';
-            def->keymap = (char *) xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "keymap");
-            xmlFree(vncport);
-            xmlFree(vnclisten);
-        } else if (STREQ((char *)prop, "sdl")) {
-            def->graphicsType = QEMUD_GRAPHICS_SDL;
-        } else {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             _("Unsupported graphics type %s"), prop);
-            goto error;
-        }
-        xmlFree(prop);
-        prop = NULL;
-    }
-    xmlXPathFreeObject(obj);
-
-    /* analysis of the disk devices */
-    obj = xmlXPathEval(BAD_CAST "/domain/devices/disk", ctxt);
-    if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
-        (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
-        for (i = 0; i < obj->nodesetval->nodeNr; i++) {
-            struct qemud_vm_disk_def *disk;
-            if (VIR_ALLOC(disk) < 0) {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
-                           "%s", _("failed to allocate space for disk string"));
-                goto error;
-            }
-            if (qemudParseDiskXML(conn, disk, obj->nodesetval->nodeTab[i]) < 0) {
-                VIR_FREE(disk);
-                goto error;
-            }
-            def->ndisks++;
-            if (i == 0) {
-                disk->next = NULL;
-                def->disks = disk;
-            } else {
-                struct qemud_vm_disk_def *ptr = def->disks;
-                while (ptr) {
-                    if (!ptr->next || qemudDiskCompare(disk, ptr->next) < 0) {
-                        disk->next = ptr->next;
-                        ptr->next = disk;
-                        break;
-                    }
-                    ptr = ptr->next;
-                }
-            }
-        }
-    }
-    xmlXPathFreeObject(obj);
-    obj = NULL;
-
-    /* analysis of the character devices */
-    if (qemudParseCharXMLDevices(conn, ctxt,
-                                 "/domain/devices/parallel",
-                                 &def->nparallels,
-                                 &def->parallels) < 0)
-        goto error;
-    if (qemudParseCharXMLDevices(conn, ctxt,
-                                 "/domain/devices/serial",
-                                 &def->nserials,
-                                 &def->serials) < 0)
-        goto error;
-
-    /*
-     * If no serial devices were listed, then look for console
-     * devices which is the legacy syntax for the same thing
-     */
-    if (def->nserials == 0) {
-        obj = xmlXPathEval(BAD_CAST "/domain/devices/console", ctxt);
-        if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
-            (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
-            struct qemud_vm_chr_def *chr;
-            if (VIR_ALLOC(chr) < 0) {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
-                                 "%s",
-                                 _("failed to allocate space for char device"));
-                goto error;
-            }
-
-            if (qemudParseCharXML(conn, chr, 0, obj->nodesetval->nodeTab[0]) < 0) {
-                VIR_FREE(chr);
-                goto error;
-            }
-            def->nserials = 1;
-            def->serials = chr;
-        }
-        xmlXPathFreeObject(obj);
-    }
-
-
-    /* analysis of the network devices */
-    obj = xmlXPathEval(BAD_CAST "/domain/devices/interface", ctxt);
-    if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
-        (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
-        struct qemud_vm_net_def *prev = NULL;
-        for (i = 0; i < obj->nodesetval->nodeNr; i++) {
-            struct qemud_vm_net_def *net;
-            if (VIR_ALLOC(net) < 0) {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
-                           "%s", _("failed to allocate space for net string"));
-                goto error;
-            }
-            if (qemudParseInterfaceXML(conn, net, obj->nodesetval->nodeTab[i]) < 0) {
-                VIR_FREE(net);
-                goto error;
-            }
-            def->nnets++;
-            net->next = NULL;
-            if (i == 0) {
-                def->nets = net;
-            } else {
-                prev->next = net;
-            }
-            prev = net;
-        }
-    }
-    xmlXPathFreeObject(obj);
-
-    /* analysis of the input devices */
-    obj = xmlXPathEval(BAD_CAST "/domain/devices/input", ctxt);
-    if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
-        (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
-        struct qemud_vm_input_def *prev = NULL;
-        for (i = 0; i < obj->nodesetval->nodeNr; i++) {
-            struct qemud_vm_input_def *input;
-            if (VIR_ALLOC(input) < 0) {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
-                         "%s", _("failed to allocate space for input string"));
-                goto error;
-            }
-            if (qemudParseInputXML(conn, def, input, obj->nodesetval->nodeTab[i]) < 0) {
-                VIR_FREE(input);
-                goto error;
-            }
-            /* Mouse + PS/2 is implicit with graphics, so don't store it */
-            if (input->bus == QEMU_INPUT_BUS_PS2 &&
-                input->type == QEMU_INPUT_TYPE_MOUSE) {
-                VIR_FREE(input);
-                continue;
-            }
-            def->ninputs++;
-            input->next = NULL;
-            if (def->inputs == NULL) {
-                def->inputs = input;
-            } else {
-                prev->next = input;
-            }
-            prev = input;
-        }
-    }
-    xmlXPathFreeObject(obj);
-
-    /* Parse sound driver xml */
-    obj = xmlXPathEval(BAD_CAST "/domain/devices/sound", ctxt);
-    if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
-        (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
-        struct qemud_vm_sound_def *prev = NULL;
-        for (i = 0; i < obj->nodesetval->nodeNr; i++) {
-
-            struct qemud_vm_sound_def *sound;
-            struct qemud_vm_sound_def *check = def->sounds;
-            int collision = 0;
-            if (VIR_ALLOC(sound) < 0) {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
-                         "%s", _("failed to allocate space for sound dev"));
-                goto error;
-            }
-            if (qemudParseSoundXML(conn, sound,
-                                   obj->nodesetval->nodeTab[i]) < 0) {
-                VIR_FREE(sound);
-                goto error;
-            }
-
-            // Check that model type isn't already present in sound dev list
-            while(check) {
-                if (check->model == sound->model) {
-                    collision = 1;
-                    break;
-                }
-                check = check->next;
-            }
-            if (collision) {
-                VIR_FREE(sound);
-                continue;
-            }
-
-            def->nsounds++;
-            sound->next = NULL;
-            if (def->sounds == NULL) {
-                def->sounds = sound;
-            } else {
-                prev->next = sound;
-            }
-            prev = sound;
-        }
-    }
-    xmlXPathFreeObject(obj);
-    obj = NULL;
-
-    /* If graphics are enabled, there's an implicit PS2 mouse */
-    if (def->graphicsType != QEMUD_GRAPHICS_NONE) {
-        int hasPS2mouse = 0;
-        struct qemud_vm_input_def *input = def->inputs;
-        while (input) {
-            if (input->type == QEMU_INPUT_TYPE_MOUSE &&
-                input->bus == QEMU_INPUT_BUS_PS2)
-                hasPS2mouse = 1;
-            input = input->next;
-        }
+                                                      "i686",
+                                                      "qemu")) == NULL)
+        return -1;
 
-        if (!hasPS2mouse) {
-            if (VIR_ALLOC(input) < 0) {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
-                         "%s", _("failed to allocate space for input string"));
-                goto error;
-            }
-            input->type = QEMU_INPUT_TYPE_MOUSE;
-            input->bus = QEMU_INPUT_BUS_PS2;
-            input->next = def->inputs;
-            def->inputs = input;
-            def->ninputs++;
-        }
+    if (stat(binary, &sb) < 0) {
+        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                         _("Cannot find QEMU binary %s: %s"), binary,
+                         strerror(errno));
+        return -1;
     }
 
-    xmlXPathFreeContext(ctxt);
-
-    return def;
+    if (qemudExtractVersionInfo(binary, &driver->qemuVersion, &ignored) < 0) {
+        return -1;
+    }
 
- error:
-    VIR_FREE(prop);
-    xmlXPathFreeObject(obj);
-    xmlXPathFreeContext(ctxt);
-    qemudFreeVMDef(def);
-    return NULL;
+    return 0;
 }
 
 
 static char *
 qemudNetworkIfaceConnect(virConnectPtr conn,
                          struct qemud_driver *driver,
-                         struct qemud_vm *vm,
-                         struct qemud_vm_net_def *net,
+                         int **tapfds,
+                         int *ntapfds,
+                         virDomainNetDefPtr net,
                          int vlan)
 {
     virNetworkObjPtr network = NULL;
     char *brname;
-    char *ifname;
     char tapfdstr[4+3+32+7];
     char *retval = NULL;
     int err;
     int tapfd = -1;
 
-    if (net->type == QEMUD_NET_NETWORK) {
-        if (!(network = virNetworkFindByName(driver->networks, net->dst.network.name))) {
+    if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
+        if (!(network = virNetworkFindByName(driver->networks, net->data.network.name))) {
             qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                              _("Network '%s' not found"),
-                             net->dst.network.name);
+                             net->data.network.name);
             goto error;
         } else if (network->def->bridge == NULL) {
             qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                              _("Network '%s' not active"),
-                             net->dst.network.name);
+                             net->data.network.name);
             goto error;
         }
         brname = network->def->bridge;
-        if (net->dst.network.ifname[0] == '\0' ||
-            STRPREFIX(net->dst.network.ifname, "vnet") ||
-            strchr(net->dst.network.ifname, '%')) {
-            strcpy(net->dst.network.ifname, "vnet%d");
-        }
-        ifname = net->dst.network.ifname;
-    } else if (net->type == QEMUD_NET_BRIDGE) {
-        brname = net->dst.bridge.brname;
-        if (net->dst.bridge.ifname[0] == '\0' ||
-            STRPREFIX(net->dst.bridge.ifname, "vnet") ||
-            strchr(net->dst.bridge.ifname, '%')) {
-            strcpy(net->dst.bridge.ifname, "vnet%d");
-        }
-        ifname = net->dst.bridge.ifname;
+    } else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
+        brname = net->data.bridge.brname;
     } else {
         qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                          _("Network type %d is not supported"), net->type);
         goto error;
     }
 
+    if (!net->ifname ||
+        STRPREFIX(net->ifname, "vnet") ||
+        strchr(net->ifname, '%')) {
+        VIR_FREE(net->ifname);
+        if (!(net->ifname = strdup("vnet%d"))) {
+            qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
+            goto error;
+        }
+    }
+
     if (!driver->brctl && (err = brInit(&driver->brctl))) {
         qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                          _("cannot initialize bridge support: %s"),
@@ -2277,7 +593,7 @@ qemudNetworkIfaceConnect(virConnectPtr conn,
     }
 
     if ((err = brAddTap(driver->brctl, brname,
-                        ifname, BR_IFNAME_MAXLEN, &tapfd))) {
+                        &net->ifname, &tapfd))) {
         if (errno == ENOTSUP) {
             /* In this particular case, give a better diagnostic. */
             qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
@@ -2287,23 +603,22 @@ qemudNetworkIfaceConnect(virConnectPtr conn,
             qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                              _("Failed to add tap interface '%s' "
                                "to bridge '%s' : %s"),
-                             ifname, brname, strerror(err));
+                             net->ifname, brname, strerror(err));
         }
         goto error;
     }
 
     snprintf(tapfdstr, sizeof(tapfdstr),
              "tap,fd=%d,script=,vlan=%d,ifname=%s",
-             tapfd, vlan, ifname);
+             tapfd, vlan, net->ifname);
 
     if (!(retval = strdup(tapfdstr)))
         goto no_memory;
 
-    if (VIR_REALLOC_N(vm->tapfds, vm->ntapfds+2) < 0)
+    if (VIR_REALLOC_N(*tapfds, (*ntapfds)+1) < 0)
         goto no_memory;
 
-    vm->tapfds[vm->ntapfds++] = tapfd;
-    vm->tapfds[vm->ntapfds]   = -1;
+    (*tapfds)[(*ntapfds)++] = tapfd;
 
     return retval;
 
@@ -2317,71 +632,71 @@ qemudNetworkIfaceConnect(virConnectPtr conn,
     return NULL;
 }
 
-static int qemudBuildCommandLineChrDevStr(struct qemud_vm_chr_def *dev,
+static int qemudBuildCommandLineChrDevStr(virDomainChrDefPtr dev,
                                           char *buf,
                                           int buflen)
 {
-    switch (dev->srcType) {
-    case QEMUD_CHR_SRC_TYPE_NULL:
+    switch (dev->type) {
+    case VIR_DOMAIN_CHR_TYPE_NULL:
         strncpy(buf, "null", buflen);
         buf[buflen-1] = '\0';
         break;
 
-    case QEMUD_CHR_SRC_TYPE_VC:
+    case VIR_DOMAIN_CHR_TYPE_VC:
         strncpy(buf, "vc", buflen);
         buf[buflen-1] = '\0';
         break;
 
-    case QEMUD_CHR_SRC_TYPE_PTY:
+    case VIR_DOMAIN_CHR_TYPE_PTY:
         strncpy(buf, "pty", buflen);
         buf[buflen-1] = '\0';
         break;
 
-    case QEMUD_CHR_SRC_TYPE_DEV:
+    case VIR_DOMAIN_CHR_TYPE_DEV:
         if (snprintf(buf, buflen, "%s",
-                     dev->srcData.file.path) >= buflen)
+                     dev->data.file.path) >= buflen)
             return -1;
         break;
 
-    case QEMUD_CHR_SRC_TYPE_FILE:
+    case VIR_DOMAIN_CHR_TYPE_FILE:
         if (snprintf(buf, buflen, "file:%s",
-                     dev->srcData.file.path) >= buflen)
+                     dev->data.file.path) >= buflen)
             return -1;
         break;
 
-    case QEMUD_CHR_SRC_TYPE_PIPE:
+    case VIR_DOMAIN_CHR_TYPE_PIPE:
         if (snprintf(buf, buflen, "pipe:%s",
-                     dev->srcData.file.path) >= buflen)
+                     dev->data.file.path) >= buflen)
             return -1;
         break;
 
-    case QEMUD_CHR_SRC_TYPE_STDIO:
+    case VIR_DOMAIN_CHR_TYPE_STDIO:
         strncpy(buf, "stdio", buflen);
         buf[buflen-1] = '\0';
         break;
 
-    case QEMUD_CHR_SRC_TYPE_UDP:
+    case VIR_DOMAIN_CHR_TYPE_UDP:
         if (snprintf(buf, buflen, "udp:%s:%s@%s:%s",
-                     dev->srcData.udp.connectHost,
-                     dev->srcData.udp.connectService,
-                     dev->srcData.udp.bindHost,
-                     dev->srcData.udp.bindService) >= buflen)
+                     dev->data.udp.connectHost,
+                     dev->data.udp.connectService,
+                     dev->data.udp.bindHost,
+                     dev->data.udp.bindService) >= buflen)
             return -1;
         break;
 
-    case QEMUD_CHR_SRC_TYPE_TCP:
+    case VIR_DOMAIN_CHR_TYPE_TCP:
         if (snprintf(buf, buflen, "%s:%s:%s%s",
-                     dev->srcData.tcp.protocol == QEMUD_CHR_SRC_TCP_PROTOCOL_TELNET ? "telnet" : "tcp",
-                     dev->srcData.tcp.host,
-                     dev->srcData.tcp.service,
-                     dev->srcData.tcp.listen ? ",listen" : "") >= buflen)
+                     dev->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET ? "telnet" : "tcp",
+                     dev->data.tcp.host,
+                     dev->data.tcp.service,
+                     dev->data.tcp.listen ? ",listen" : "") >= buflen)
             return -1;
         break;
 
-    case QEMUD_CHR_SRC_TYPE_UNIX:
+    case VIR_DOMAIN_CHR_TYPE_UNIX:
         if (snprintf(buf, buflen, "unix:%s%s",
-                     dev->srcData.nix.path,
-                     dev->srcData.nix.listen ? ",listen" : "") >= buflen)
+                     dev->data.nix.path,
+                     dev->data.nix.listen ? ",listen" : "") >= buflen)
             return -1;
         break;
     }
@@ -2395,30 +710,27 @@ static int qemudBuildCommandLineChrDevStr(struct qemud_vm_chr_def *dev,
  */
 int qemudBuildCommandLine(virConnectPtr conn,
                           struct qemud_driver *driver,
-                          struct qemud_vm *vm,
-                          char ***retargv) {
+                          virDomainObjPtr vm,
+                          int qemuCmdFlags,
+                          char ***retargv,
+                          int **tapfds,
+                          int *ntapfds,
+                          const char *migrateFrom) {
     int i;
     char memory[50];
     char vcpus[50];
-    char boot[QEMUD_MAX_BOOT_DEVS+1];
-    struct qemud_vm_disk_def *disk = vm->def->disks;
-    struct qemud_vm_net_def *net = vm->def->nets;
-    struct qemud_vm_input_def *input = vm->def->inputs;
-    struct qemud_vm_sound_def *sound = vm->def->sounds;
-    struct qemud_vm_chr_def *serial = vm->def->serials;
-    struct qemud_vm_chr_def *parallel = vm->def->parallels;
+    char boot[VIR_DOMAIN_BOOT_LAST];
+    virDomainDiskDefPtr disk = vm->def->disks;
+    virDomainNetDefPtr net = vm->def->nets;
+    virDomainInputDefPtr input = vm->def->inputs;
+    virDomainSoundDefPtr sound = vm->def->sounds;
+    virDomainChrDefPtr serial = vm->def->serials;
+    virDomainChrDefPtr parallel = vm->def->parallels;
     struct utsname ut;
     int disableKQEMU = 0;
     int qargc = 0, qarga = 0;
     char **qargv = NULL;
 
-    if (vm->qemuVersion == 0) {
-        if (qemudExtractVersionInfo(vm->def->os.binary,
-                                    &(vm->qemuVersion),
-                                    &(vm->qemuCmdFlags)) < 0)
-            return -1;
-    }
-
     uname(&ut);
 
     /* Nasty hack make i?86 look like i686 to simplify next comparison */
@@ -2433,9 +745,9 @@ int qemudBuildCommandLine(virConnectPtr conn,
      * 2. Guest is 'qemu'
      * 3. The qemu binary has the -no-kqemu flag
      */
-    if ((vm->qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU) &&
+    if ((qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU) &&
         STREQ(ut.machine, vm->def->os.arch) &&
-        vm->def->virtType == QEMUD_VIRT_QEMU)
+        vm->def->virtType == VIR_DOMAIN_VIRT_QEMU)
         disableKQEMU = 1;
 
 #define ADD_ARG_SPACE                                                   \
@@ -2461,10 +773,10 @@ int qemudBuildCommandLine(virConnectPtr conn,
     } while (0)
 
     snprintf(memory, sizeof(memory), "%lu", vm->def->memory/1024);
-    snprintf(vcpus, sizeof(vcpus), "%d", vm->def->vcpus);
+    snprintf(vcpus, sizeof(vcpus), "%lu", vm->def->vcpus);
 
 
-    ADD_ARG_LIT(vm->def->os.binary);
+    ADD_ARG_LIT(vm->def->emulator);
     ADD_ARG_LIT("-S");
     ADD_ARG_LIT("-M");
     ADD_ARG_LIT(vm->def->os.machine);
@@ -2475,7 +787,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
     ADD_ARG_LIT("-smp");
     ADD_ARG_LIT(vcpus);
 
-    if (vm->qemuCmdFlags & QEMUD_CMD_FLAG_NAME) {
+    if (qemuCmdFlags & QEMUD_CMD_FLAG_NAME) {
         ADD_ARG_LIT("-name");
         ADD_ARG_LIT(vm->def->name);
     }
@@ -2486,7 +798,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
      * if you ask for nographic. So we have to make sure we override
      * these defaults ourselves...
      */
-    if (vm->def->graphicsType == QEMUD_GRAPHICS_NONE)
+    if (!vm->def->graphics)
         ADD_ARG_LIT("-nographic");
 
     ADD_ARG_LIT("-monitor");
@@ -2495,26 +807,26 @@ int qemudBuildCommandLine(virConnectPtr conn,
     if (vm->def->localtime)
         ADD_ARG_LIT("-localtime");
 
-    if ((vm->qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) &&
-        vm->def->noReboot)
+    if ((qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) &&
+        vm->def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART)
         ADD_ARG_LIT("-no-reboot");
 
-    if (!(vm->def->features & QEMUD_FEATURE_ACPI))
+    if (!(vm->def->features & (1 << VIR_DOMAIN_FEATURE_ACPI)))
         ADD_ARG_LIT("-no-acpi");
 
-    if (!vm->def->os.bootloader[0]) {
+    if (!vm->def->os.bootloader) {
         for (i = 0 ; i < vm->def->os.nBootDevs ; i++) {
             switch (vm->def->os.bootDevs[i]) {
-            case QEMUD_BOOT_CDROM:
+            case VIR_DOMAIN_BOOT_CDROM:
                 boot[i] = 'd';
                 break;
-            case QEMUD_BOOT_FLOPPY:
+            case VIR_DOMAIN_BOOT_FLOPPY:
                 boot[i] = 'a';
                 break;
-            case QEMUD_BOOT_DISK:
+            case VIR_DOMAIN_BOOT_DISK:
                 boot[i] = 'c';
                 break;
-            case QEMUD_BOOT_NET:
+            case VIR_DOMAIN_BOOT_NET:
                 boot[i] = 'n';
                 break;
             default:
@@ -2526,15 +838,15 @@ int qemudBuildCommandLine(virConnectPtr conn,
         ADD_ARG_LIT("-boot");
         ADD_ARG_LIT(boot);
 
-        if (vm->def->os.kernel[0]) {
+        if (vm->def->os.kernel) {
             ADD_ARG_LIT("-kernel");
             ADD_ARG_LIT(vm->def->os.kernel);
         }
-        if (vm->def->os.initrd[0]) {
+        if (vm->def->os.initrd) {
             ADD_ARG_LIT("-initrd");
             ADD_ARG_LIT(vm->def->os.initrd);
         }
-        if (vm->def->os.cmdline[0]) {
+        if (vm->def->os.cmdline) {
             ADD_ARG_LIT("-append");
             ADD_ARG_LIT(vm->def->os.cmdline);
         }
@@ -2544,20 +856,20 @@ int qemudBuildCommandLine(virConnectPtr conn,
     }
 
     /* If QEMU supports -drive param instead of old -hda, -hdb, -cdrom .. */
-    if (vm->qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) {
+    if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) {
         int bootCD = 0, bootFloppy = 0, bootDisk = 0;
 
         /* If QEMU supports boot=on for -drive param... */
-        if (vm->qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE_BOOT) {
+        if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE_BOOT) {
             for (i = 0 ; i < vm->def->os.nBootDevs ; i++) {
                 switch (vm->def->os.bootDevs[i]) {
-                case QEMUD_BOOT_CDROM:
+                case VIR_DOMAIN_BOOT_CDROM:
                     bootCD = 1;
                     break;
-                case QEMUD_BOOT_FLOPPY:
+                case VIR_DOMAIN_BOOT_FLOPPY:
                     bootFloppy = 1;
                     break;
-                case QEMUD_BOOT_DISK:
+                case VIR_DOMAIN_BOOT_DISK:
                     bootDisk = 1;
                     break;
                 }
@@ -2569,6 +881,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
             const char *media = NULL;
             int bootable = 0;
             int idx = virDiskNameToIndex(disk->dst);
+            const char *bus = virDomainDiskQEMUBusTypeToString(disk->bus);
 
             if (idx < 0) {
                 qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
@@ -2576,29 +889,30 @@ int qemudBuildCommandLine(virConnectPtr conn,
                 goto error;
             }
 
-            if (disk->device == QEMUD_DISK_CDROM)
+            if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
                 media = "media=cdrom,";
 
             switch (disk->device) {
-            case QEMUD_DISK_CDROM:
+            case VIR_DOMAIN_DISK_DEVICE_CDROM:
                 bootable = bootCD;
                 bootCD = 0;
                 break;
-            case QEMUD_DISK_FLOPPY:
+            case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
                 bootable = bootFloppy;
                 bootFloppy = 0;
                 break;
-            case QEMUD_DISK_DISK:
+            case VIR_DOMAIN_DISK_DEVICE_DISK:
                 bootable = bootDisk;
                 bootDisk = 0;
                 break;
             }
 
             snprintf(opt, PATH_MAX, "file=%s,if=%s,%sindex=%d%s",
-                     disk->src, qemudBusIdToName(disk->bus, 1),
+                     disk->src, bus,
                      media ? media : "",
                      idx,
-                     bootable && disk->device == QEMUD_DISK_DISK
+                     bootable &&
+                     disk->device == VIR_DOMAIN_DISK_DEVICE_DISK
                      ? ",boot=on" : "");
 
             ADD_ARG_LIT("-drive");
@@ -2611,8 +925,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
             char file[PATH_MAX];
 
             if (STREQ(disk->dst, "hdc") &&
-                disk->device == QEMUD_DISK_CDROM) {
-                if (disk->src[0]) {
+                disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
+                if (disk->src) {
                     snprintf(dev, NAME_MAX, "-%s", "cdrom");
                 } else {
                     disk = disk->next;
@@ -2652,7 +966,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
                          net->mac[2], net->mac[3],
                          net->mac[4], net->mac[5],
                          vlan,
-                         (net->model[0] ? ",model=" : ""), net->model) >= sizeof(nic))
+                         (net->model ? ",model=" : ""),
+                         (net->model ? net->model : "")) >= sizeof(nic))
                 goto error;
 
             ADD_ARG_LIT("-net");
@@ -2660,22 +975,24 @@ int qemudBuildCommandLine(virConnectPtr conn,
             ADD_ARG_LIT("-net");
 
             switch (net->type) {
-            case QEMUD_NET_NETWORK:
-            case QEMUD_NET_BRIDGE:
+            case VIR_DOMAIN_NET_TYPE_NETWORK:
+            case VIR_DOMAIN_NET_TYPE_BRIDGE:
                 {
-                    char *tap = qemudNetworkIfaceConnect(conn, driver, vm, net, vlan);
+                    char *tap = qemudNetworkIfaceConnect(conn, driver,
+                                                         tapfds, ntapfds,
+                                                         net, vlan);
                     if (tap == NULL)
                         goto error;
                     ADD_ARG(tap);
                     break;
                 }
 
-            case QEMUD_NET_ETHERNET:
+            case VIR_DOMAIN_NET_TYPE_ETHERNET:
                 {
                     char arg[PATH_MAX];
                     if (snprintf(arg, PATH_MAX-1, "tap,ifname=%s,script=%s,vlan=%d",
-                                 net->dst.ethernet.ifname,
-                                 net->dst.ethernet.script,
+                                 net->ifname,
+                                 net->data.ethernet.script,
                                  vlan) >= (PATH_MAX-1))
                         goto error;
 
@@ -2683,27 +1000,27 @@ int qemudBuildCommandLine(virConnectPtr conn,
                 }
                 break;
 
-            case QEMUD_NET_CLIENT:
-            case QEMUD_NET_SERVER:
-            case QEMUD_NET_MCAST:
+            case VIR_DOMAIN_NET_TYPE_CLIENT:
+            case VIR_DOMAIN_NET_TYPE_SERVER:
+            case VIR_DOMAIN_NET_TYPE_MCAST:
                 {
                     char arg[PATH_MAX];
                     const char *mode = NULL;
                     switch (net->type) {
-                    case QEMUD_NET_CLIENT:
+                    case VIR_DOMAIN_NET_TYPE_CLIENT:
                         mode = "connect";
                         break;
-                    case QEMUD_NET_SERVER:
+                    case VIR_DOMAIN_NET_TYPE_SERVER:
                         mode = "listen";
                         break;
-                    case QEMUD_NET_MCAST:
+                    case VIR_DOMAIN_NET_TYPE_MCAST:
                         mode = "mcast";
                         break;
                     }
                     if (snprintf(arg, PATH_MAX-1, "socket,%s=%s:%d,vlan=%d",
                                  mode,
-                                 net->dst.socket.address,
-                                 net->dst.socket.port,
+                                 net->data.socket.address,
+                                 net->data.socket.port,
                                  vlan) >= (PATH_MAX-1))
                         goto error;
 
@@ -2711,7 +1028,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
                 }
                 break;
 
-            case QEMUD_NET_USER:
+            case VIR_DOMAIN_NET_TYPE_USER:
             default:
                 {
                     char arg[PATH_MAX];
@@ -2763,19 +1080,20 @@ int qemudBuildCommandLine(virConnectPtr conn,
 
     ADD_ARG_LIT("-usb");
     while (input) {
-        if (input->bus == QEMU_INPUT_BUS_USB) {
+        if (input->bus == VIR_DOMAIN_INPUT_BUS_USB) {
             ADD_ARG_LIT("-usbdevice");
-            ADD_ARG_LIT(input->type == QEMU_INPUT_TYPE_MOUSE ? "mouse" : "tablet");
+            ADD_ARG_LIT(input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ? "mouse" : "tablet");
         }
 
         input = input->next;
     }
 
-    if (vm->def->graphicsType == QEMUD_GRAPHICS_VNC) {
+    if (vm->def->graphics &&
+        vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
         char vncdisplay[PATH_MAX];
         int ret;
 
-        if (vm->qemuCmdFlags & QEMUD_CMD_FLAG_VNC_COLON) {
+        if (qemuCmdFlags & QEMUD_CMD_FLAG_VNC_COLON) {
             char options[PATH_MAX] = "";
             if (driver->vncTLS) {
                 strcat(options, ",tls");
@@ -2789,25 +1107,24 @@ int qemudBuildCommandLine(virConnectPtr conn,
                 options[sizeof(options)-1] = '\0';
             }
             ret = snprintf(vncdisplay, sizeof(vncdisplay), "%s:%d%s",
-                           vm->def->vncListen,
-                           vm->def->vncActivePort - 5900,
+                           vm->def->graphics->data.vnc.listenAddr,
+                           vm->def->graphics->data.vnc.port - 5900,
                            options);
         } else {
             ret = snprintf(vncdisplay, sizeof(vncdisplay), "%d",
-                           vm->def->vncActivePort - 5900);
+                           vm->def->graphics->data.vnc.port - 5900);
         }
         if (ret < 0 || ret >= (int)sizeof(vncdisplay))
             goto error;
 
         ADD_ARG_LIT("-vnc");
         ADD_ARG_LIT(vncdisplay);
-        if (vm->def->keymap) {
+        if (vm->def->graphics->data.vnc.keymap) {
             ADD_ARG_LIT("-k");
-            ADD_ARG_LIT(vm->def->keymap);
+            ADD_ARG_LIT(vm->def->graphics->data.vnc.keymap);
         }
-    } else if (vm->def->graphicsType == QEMUD_GRAPHICS_NONE) {
-        /* Nada - we added -nographic earlier in this function */
-    } else {
+    } else if (vm->def->graphics &&
+               vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
         /* SDL is the default. no args needed */
     }
 
@@ -2819,7 +1136,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
             goto no_memory;
 
         while(sound && size > 0) {
-            const char *model = qemudSoundModelToString(sound->model);
+            const char *model = virDomainSoundModelTypeToString(sound->model);
             if (!model) {
                 VIR_FREE(modstr);
                 qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
@@ -2836,9 +1153,9 @@ int qemudBuildCommandLine(virConnectPtr conn,
         ADD_ARG(modstr);
     }
 
-    if (vm->migrateFrom[0]) {
+    if (migrateFrom) {
         ADD_ARG_LIT("-incoming");
-        ADD_ARG_LIT(vm->migrateFrom);
+        ADD_ARG_LIT(migrateFrom);
     }
 
     ADD_ARG(NULL);
@@ -2850,12 +1167,12 @@ int qemudBuildCommandLine(virConnectPtr conn,
     qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
                      "%s", _("failed to allocate space for argv string"));
  error:
-    if (vm->tapfds) {
-        for (i = 0; vm->tapfds[i] != -1; i++)
-            close(vm->tapfds[i]);
-        VIR_FREE(vm->tapfds);
-        vm->tapfds = NULL;
-        vm->ntapfds = 0;
+    if (tapfds &&
+        *tapfds) {
+        for (i = 0; ntapfds; i++)
+            close((*tapfds)[i]);
+        VIR_FREE(*tapfds);
+        *ntapfds = 0;
     }
     if (qargv) {
         for (i = 0 ; i < qargc ; i++)
@@ -2870,755 +1187,4 @@ int qemudBuildCommandLine(virConnectPtr conn,
 }
 
 
-/* Save a guest's config data into a persistent file */
-static int qemudSaveConfig(virConnectPtr conn,
-                           struct qemud_driver *driver,
-                           struct qemud_vm *vm,
-                           struct qemud_vm_def *def) {
-    char *xml;
-    int fd = -1, ret = -1;
-    int towrite;
-
-    if (!(xml = qemudGenerateXML(conn, driver, vm, def, 0)))
-        return -1;
-
-    if ((fd = open(vm->configFile,
-                   O_WRONLY | O_CREAT | O_TRUNC,
-                   S_IRUSR | S_IWUSR )) < 0) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         _("cannot create config file %s: %s"),
-                         vm->configFile, strerror(errno));
-        goto cleanup;
-    }
-
-    towrite = strlen(xml);
-    if (safewrite(fd, xml, towrite) < 0) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         _("cannot write config file %s: %s"),
-                         vm->configFile, strerror(errno));
-        goto cleanup;
-    }
-
-    if (close(fd) < 0) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         _("cannot save config file %s: %s"),
-                         vm->configFile, strerror(errno));
-        goto cleanup;
-    }
-
-    ret = 0;
-
- cleanup:
-    if (fd != -1)
-        close(fd);
-
-    VIR_FREE(xml);
-
-    return ret;
-}
-
-struct qemud_vm_device_def *
-qemudParseVMDeviceDef(virConnectPtr conn,
-                      const struct qemud_vm_def *def,
-                      const char *xmlStr)
-{
-    xmlDocPtr xml;
-    xmlNodePtr node;
-    struct qemud_vm_device_def *dev;
-
-    if (VIR_ALLOC(dev) < 0) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
-        return NULL;
-    }
-
-    if (!(xml = xmlReadDoc(BAD_CAST xmlStr, "device.xml", NULL,
-                           XML_PARSE_NOENT | XML_PARSE_NONET |
-                           XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_XML_ERROR, NULL);
-        goto error;
-    }
-
-    node = xmlDocGetRootElement(xml);
-    if (node == NULL) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_XML_ERROR,
-                         "%s", _("missing root element"));
-        goto error;
-    }
-    if (xmlStrEqual(node->name, BAD_CAST "disk")) {
-        dev->type = QEMUD_DEVICE_DISK;
-        qemudParseDiskXML(conn, &(dev->data.disk), node);
-    } else if (xmlStrEqual(node->name, BAD_CAST "interface")) {
-        dev->type = QEMUD_DEVICE_NET;
-        qemudParseInterfaceXML(conn, &(dev->data.net), node);
-    } else if (xmlStrEqual(node->name, BAD_CAST "input")) {
-        dev->type = QEMUD_DEVICE_DISK;
-        qemudParseInputXML(conn, def, &(dev->data.input), node);
-    } else if (xmlStrEqual(node->name, BAD_CAST "sound")) {
-        dev->type = QEMUD_DEVICE_SOUND;
-        qemudParseSoundXML(conn, &(dev->data.sound), node);
-    } else {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_XML_ERROR,
-                         "%s", _("unknown device type"));
-        goto error;
-    }
-
-    xmlFreeDoc(xml);
-
-    return dev;
-
-  error:
-    if (xml) xmlFreeDoc(xml);
-    VIR_FREE(dev);
-    return NULL;
-}
-
-struct qemud_vm_def *
-qemudParseVMDef(virConnectPtr conn,
-                struct qemud_driver *driver,
-                const char *xmlStr,
-                const char *displayName) {
-    xmlDocPtr xml;
-    struct qemud_vm_def *def = NULL;
-
-    if (!(xml = xmlReadDoc(BAD_CAST xmlStr, displayName ? displayName : "domain.xml", NULL,
-                           XML_PARSE_NOENT | XML_PARSE_NONET |
-                           XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_XML_ERROR, NULL);
-        return NULL;
-    }
-
-    def = qemudParseXML(conn, driver, xml);
-
-    xmlFreeDoc(xml);
-
-    return def;
-}
-
-struct qemud_vm *
-qemudAssignVMDef(virConnectPtr conn,
-                 struct qemud_driver *driver,
-                 struct qemud_vm_def *def)
-{
-    struct qemud_vm *vm = NULL;
-
-    if ((vm = qemudFindVMByName(driver, def->name))) {
-        if (!qemudIsActiveVM(vm)) {
-            qemudFreeVMDef(vm->def);
-            vm->def = def;
-        } else {
-            if (vm->newDef)
-                qemudFreeVMDef(vm->newDef);
-            vm->newDef = def;
-        }
-        /* Reset version, because the emulator path might have changed */
-        vm->qemuVersion = 0;
-        vm->qemuCmdFlags = 0;
-        return vm;
-    }
-
-    if (VIR_ALLOC(vm) < 0) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
-                         "%s", _("failed to allocate space for vm string"));
-        return NULL;
-    }
-
-    vm->stdin = -1;
-    vm->stdout = -1;
-    vm->stderr = -1;
-    vm->monitor = -1;
-    vm->pid = -1;
-    vm->id = -1;
-    vm->state = VIR_DOMAIN_SHUTOFF;
-    vm->def = def;
-    vm->next = driver->vms;
-
-    driver->vms = vm;
-    driver->ninactivevms++;
-
-    return vm;
-}
-
-void
-qemudRemoveInactiveVM(struct qemud_driver *driver,
-                      struct qemud_vm *vm)
-{
-    struct qemud_vm *prev = NULL, *curr;
-
-    curr = driver->vms;
-    while (curr != vm) {
-        prev = curr;
-        curr = curr->next;
-    }
-
-    if (curr) {
-        if (prev)
-            prev->next = curr->next;
-        else
-            driver->vms = curr->next;
-
-        driver->ninactivevms--;
-    }
-
-    qemudFreeVM(vm);
-}
-
-int
-qemudSaveVMDef(virConnectPtr conn,
-               struct qemud_driver *driver,
-               struct qemud_vm *vm,
-               struct qemud_vm_def *def) {
-    if (vm->configFile[0] == '\0') {
-        int err;
-
-        if ((err = virFileMakePath(driver->configDir))) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             _("cannot create config directory %s: %s"),
-                             driver->configDir, strerror(err));
-            return -1;
-        }
-
-        if (virFileBuildPath(driver->configDir, def->name, ".xml",
-                             vm->configFile, PATH_MAX) < 0) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("cannot construct config file path"));
-            return -1;
-        }
-
-        if (virFileBuildPath(driver->autostartDir, def->name, ".xml",
-                             vm->autostartLink, PATH_MAX) < 0) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("cannot construct autostart link path"));
-            vm->configFile[0] = '\0';
-            return -1;
-        }
-    }
-
-    return qemudSaveConfig(conn, driver, vm, def);
-}
-
-
-static struct qemud_vm *
-qemudLoadConfig(struct qemud_driver *driver,
-                const char *file,
-                const char *path,
-                const char *xml,
-                const char *autostartLink) {
-    struct qemud_vm_def *def;
-    struct qemud_vm *vm;
-
-    if (!(def = qemudParseVMDef(NULL, driver, xml, file))) {
-        virErrorPtr err = virGetLastError();
-        qemudLog(QEMUD_WARN, _("Error parsing QEMU guest config '%s' : %s"),
-                 path, (err ? err->message :
-                        _("BUG: unknown error - please report it\n")));
-        return NULL;
-    }
-
-    if (!virFileMatchesNameSuffix(file, def->name, ".xml")) {
-        qemudLog(QEMUD_WARN,
-                 _("QEMU guest config filename '%s'"
-                   " does not match guest name '%s'"),
-                 path, def->name);
-        qemudFreeVMDef(def);
-        return NULL;
-    }
-
-    if (!(vm = qemudAssignVMDef(NULL, driver, def))) {
-        qemudLog(QEMUD_WARN,
-                 _("Failed to load QEMU guest config '%s': out of memory"),
-                 path);
-        qemudFreeVMDef(def);
-        return NULL;
-    }
-
-    strncpy(vm->configFile, path, PATH_MAX);
-    vm->configFile[PATH_MAX-1] = '\0';
-
-    strncpy(vm->autostartLink, autostartLink, PATH_MAX);
-    vm->autostartLink[PATH_MAX-1] = '\0';
-
-    vm->autostart = virFileLinkPointsTo(vm->autostartLink, vm->configFile);
-
-    return vm;
-}
-
-static
-int qemudScanConfigDir(struct qemud_driver *driver,
-                       const char *configDir,
-                       const char *autostartDir) {
-    DIR *dir;
-    struct dirent *entry;
-
-    if (!(dir = opendir(configDir))) {
-        if (errno == ENOENT)
-            return 0;
-        qemudLog(QEMUD_ERR, _("Failed to open dir '%s': %s"),
-                 configDir, strerror(errno));
-        return -1;
-    }
-
-    while ((entry = readdir(dir))) {
-        char *xml;
-        char path[PATH_MAX];
-        char autostartLink[PATH_MAX];
-
-        if (entry->d_name[0] == '.')
-            continue;
-
-        if (!virFileHasSuffix(entry->d_name, ".xml"))
-            continue;
-
-        if (virFileBuildPath(configDir, entry->d_name, NULL, path, PATH_MAX) < 0) {
-            qemudLog(QEMUD_WARN, _("Config filename '%s/%s' is too long"),
-                     configDir, entry->d_name);
-            continue;
-        }
-
-        if (virFileBuildPath(autostartDir, entry->d_name, NULL,
-                             autostartLink, PATH_MAX) < 0) {
-            qemudLog(QEMUD_WARN, _("Autostart link path '%s/%s' is too long"),
-                     autostartDir, entry->d_name);
-            continue;
-        }
-
-        if (virFileReadAll(path, QEMUD_MAX_XML_LEN, &xml) < 0)
-            continue;
-
-        qemudLoadConfig(driver, entry->d_name, path, xml, autostartLink);
-
-        VIR_FREE(xml);
-    }
-
-    closedir(dir);
-
-    return 0;
-}
-
-/* Scan for all guest and network config files */
-int qemudScanConfigs(struct qemud_driver *driver) {
-    if (qemudScanConfigDir(driver, driver->configDir, driver->autostartDir) < 0)
-        return -1;
-
-    return 0;
-}
-
-static int qemudGenerateXMLChar(virBufferPtr buf,
-                                const struct qemud_vm_chr_def *dev,
-                                const char *type)
-{
-    const char *const types[] = {
-        "null",
-        "vc",
-        "pty",
-        "dev",
-        "file",
-        "pipe",
-        "stdio",
-        "udp",
-        "tcp",
-        "unix"
-    };
-    verify_true(ARRAY_CARDINALITY(types) == QEMUD_CHR_SRC_TYPE_LAST);
-
-    /* Compat with legacy  <console tty='/dev/pts/5'/> syntax */
-    if (STREQ(type, "console") &&
-        dev->srcType == QEMUD_CHR_SRC_TYPE_PTY &&
-        dev->srcData.file.path[0] != '\0') {
-        virBufferVSprintf(buf, "    <%s type='%s' tty='%s'>\n",
-                          type, types[dev->srcType],
-                          dev->srcData.file.path);
-    } else {
-        virBufferVSprintf(buf, "    <%s type='%s'>\n",
-                          type, types[dev->srcType]);
-    }
-
-    switch (dev->srcType) {
-    case QEMUD_CHR_SRC_TYPE_NULL:
-    case QEMUD_CHR_SRC_TYPE_VC:
-    case QEMUD_CHR_SRC_TYPE_STDIO:
-        /* nada */
-        break;
-
-    case QEMUD_CHR_SRC_TYPE_PTY:
-    case QEMUD_CHR_SRC_TYPE_DEV:
-    case QEMUD_CHR_SRC_TYPE_FILE:
-    case QEMUD_CHR_SRC_TYPE_PIPE:
-        if (dev->srcType != QEMUD_CHR_SRC_TYPE_PTY ||
-            dev->srcData.file.path[0]) {
-            virBufferVSprintf(buf, "      <source path='%s'/>\n",
-                              dev->srcData.file.path);
-        }
-        break;
-
-    case QEMUD_CHR_SRC_TYPE_UDP:
-        if (dev->srcData.udp.bindService[0] != '\0' &&
-            dev->srcData.udp.bindHost[0] != '\0') {
-            virBufferVSprintf(buf, "      <source mode='bind' host='%s' service='%s'/>\n",
-                              dev->srcData.udp.bindHost,
-                              dev->srcData.udp.bindService);
-        } else if (dev->srcData.udp.bindHost[0] !='\0') {
-            virBufferVSprintf(buf, "      <source mode='bind' host='%s'/>\n",
-                              dev->srcData.udp.bindHost);
-        } else if (dev->srcData.udp.bindService[0] != '\0') {
-            virBufferVSprintf(buf, "      <source mode='bind' service='%s'/>\n",
-                              dev->srcData.udp.bindService);
-        }
-
-        if (dev->srcData.udp.connectService[0] != '\0' &&
-            dev->srcData.udp.connectHost[0] != '\0') {
-            virBufferVSprintf(buf, "      <source mode='connect' host='%s' service='%s'/>\n",
-                              dev->srcData.udp.connectHost,
-                              dev->srcData.udp.connectService);
-        } else if (dev->srcData.udp.connectHost[0] != '\0') {
-            virBufferVSprintf(buf, "      <source mode='connect' host='%s'/>\n",
-                              dev->srcData.udp.connectHost);
-        } else if (dev->srcData.udp.connectService[0] != '\0') {
-            virBufferVSprintf(buf, "      <source mode='connect' service='%s'/>\n",
-                              dev->srcData.udp.connectService);
-        }
-        break;
-
-    case QEMUD_CHR_SRC_TYPE_TCP:
-        virBufferVSprintf(buf, "      <source mode='%s' host='%s' service='%s'/>\n",
-                          dev->srcData.tcp.listen ? "bind" : "connect",
-                          dev->srcData.tcp.host,
-                          dev->srcData.tcp.service);
-        virBufferVSprintf(buf, "      <protocol type='%s'/>\n",
-                          dev->srcData.tcp.protocol == QEMUD_CHR_SRC_TCP_PROTOCOL_TELNET
-                          ? "telnet" : "raw");
-        break;
-
-    case QEMUD_CHR_SRC_TYPE_UNIX:
-        virBufferVSprintf(buf, "      <source mode='%s' path='%s'/>\n",
-                          dev->srcData.nix.listen ? "bind" : "connect",
-                          dev->srcData.nix.path);
-        break;
-    }
-
-    virBufferVSprintf(buf, "      <target port='%d'/>\n",
-                      dev->dstPort);
-
-    virBufferVSprintf(buf, "    </%s>\n",
-                      type);
-
-    return 0;
-}
-
-
-/* Generate an XML document describing the guest's configuration */
-char *qemudGenerateXML(virConnectPtr conn,
-                       struct qemud_driver *driver ATTRIBUTE_UNUSED,
-                       struct qemud_vm *vm,
-                       struct qemud_vm_def *def,
-                       int live) {
-    virBuffer buf = VIR_BUFFER_INITIALIZER;
-    unsigned char *uuid;
-    char uuidstr[VIR_UUID_STRING_BUFLEN];
-    const struct qemud_vm_disk_def *disk;
-    const struct qemud_vm_net_def *net;
-    const struct qemud_vm_input_def *input;
-    const struct qemud_vm_sound_def *sound;
-    const struct qemud_vm_chr_def *chr;
-    const char *type = NULL, *tmp;
-    int n, allones = 1;
-
-    if (!(type = qemudVirtTypeToString(def->virtType))) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         _("unexpected domain type %d"), def->virtType);
-        goto cleanup;
-    }
-
-    if (qemudIsActiveVM(vm) && live)
-        virBufferVSprintf(&buf, "<domain type='%s' id='%d'>\n", type, vm->id);
-    else
-        virBufferVSprintf(&buf, "<domain type='%s'>\n", type);
-
-    virBufferVSprintf(&buf, "  <name>%s</name>\n", def->name);
-
-    uuid = def->uuid;
-    virUUIDFormat(uuid, uuidstr);
-    virBufferVSprintf(&buf, "  <uuid>%s</uuid>\n", uuidstr);
-
-    virBufferVSprintf(&buf, "  <memory>%lu</memory>\n", def->maxmem);
-    virBufferVSprintf(&buf, "  <currentMemory>%lu</currentMemory>\n", def->memory);
-
-    for (n = 0 ; n < QEMUD_CPUMASK_LEN ; n++)
-        if (def->cpumask[n] != 1)
-            allones = 0;
-
-    if (allones) {
-        virBufferVSprintf(&buf, "  <vcpu>%d</vcpu>\n", def->vcpus);
-    } else {
-        char *cpumask = NULL;
-        if ((cpumask = virSaveCpuSet(conn, def->cpumask, QEMUD_CPUMASK_LEN)) == NULL) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
-                             "%s", _("allocating cpu mask"));
-            goto cleanup;
-        }
-        virBufferVSprintf(&buf, "  <vcpu cpuset='%s'>%d</vcpu>\n", cpumask, def->vcpus);
-        VIR_FREE(cpumask);
-    }
-
-    if (def->os.bootloader[0])
-        virBufferVSprintf(&buf, "  <bootloader>%s</bootloader>\n", def->os.bootloader);
-    virBufferAddLit(&buf, "  <os>\n");
-
-    if (def->virtType == QEMUD_VIRT_QEMU)
-        virBufferVSprintf(&buf, "    <type arch='%s' machine='%s'>%s</type>\n",
-                          def->os.arch, def->os.machine, def->os.type);
-    else
-        virBufferVSprintf(&buf, "    <type>%s</type>\n", def->os.type);
-
-    if (!def->os.bootloader[0]) {
-        if (def->os.kernel[0])
-            virBufferVSprintf(&buf, "    <kernel>%s</kernel>\n", def->os.kernel);
-        if (def->os.initrd[0])
-            virBufferVSprintf(&buf, "    <initrd>%s</initrd>\n", def->os.initrd);
-        if (def->os.cmdline[0])
-            virBufferVSprintf(&buf, "    <cmdline>%s</cmdline>\n", def->os.cmdline);
-
-        for (n = 0 ; n < def->os.nBootDevs ; n++) {
-            const char *boottype = "hd";
-            switch (def->os.bootDevs[n]) {
-            case QEMUD_BOOT_FLOPPY:
-                boottype = "fd";
-                break;
-            case QEMUD_BOOT_DISK:
-                boottype = "hd";
-                break;
-            case QEMUD_BOOT_CDROM:
-                boottype = "cdrom";
-                break;
-            case QEMUD_BOOT_NET:
-                boottype = "network";
-                break;
-            }
-            virBufferVSprintf(&buf, "    <boot dev='%s'/>\n", boottype);
-        }
-    }
-
-    virBufferAddLit(&buf, "  </os>\n");
-
-    if (def->features & QEMUD_FEATURE_ACPI) {
-        virBufferAddLit(&buf, "  <features>\n");
-        virBufferAddLit(&buf, "    <acpi/>\n");
-        virBufferAddLit(&buf, "  </features>\n");
-    }
-
-    virBufferVSprintf(&buf, "  <clock offset='%s'/>\n", def->localtime ? "localtime" : "utc");
-
-    virBufferAddLit(&buf, "  <on_poweroff>destroy</on_poweroff>\n");
-    if (def->noReboot)
-        virBufferAddLit(&buf, "  <on_reboot>destroy</on_reboot>\n");
-    else
-        virBufferAddLit(&buf, "  <on_reboot>restart</on_reboot>\n");
-
-    virBufferAddLit(&buf, "  <on_crash>destroy</on_crash>\n");
-    virBufferAddLit(&buf, "  <devices>\n");
-
-    virBufferVSprintf(&buf, "    <emulator>%s</emulator>\n", def->os.binary);
-
-    disk = def->disks;
-    while (disk) {
-        const char *types[] = {
-            "block",
-            "file",
-        };
-        const char *typeAttrs[] = {
-            "dev",
-            "file",
-        };
-        const char *devices[] = {
-            "disk",
-            "cdrom",
-            "floppy",
-        };
-        virBufferVSprintf(&buf, "    <disk type='%s' device='%s'>\n",
-                          types[disk->type], devices[disk->device]);
-
-        if (disk->src[0])
-            virBufferVSprintf(&buf, "      <source %s='%s'/>\n",
-                              typeAttrs[disk->type], disk->src);
-
-        virBufferVSprintf(&buf, "      <target dev='%s' bus='%s'/>\n",
-                          disk->dst, qemudBusIdToName(disk->bus, 0));
-
-        if (disk->readonly)
-            virBufferAddLit(&buf, "      <readonly/>\n");
-
-        virBufferAddLit(&buf, "    </disk>\n");
-
-        disk = disk->next;
-    }
-
-    net = def->nets;
-    while (net) {
-        const char *types[] = {
-            "user",
-            "ethernet",
-            "server",
-            "client",
-            "mcast",
-            "network",
-            "bridge",
-        };
-        virBufferVSprintf(&buf, "    <interface type='%s'>\n",
-                          types[net->type]);
-
-        virBufferVSprintf(&buf, "      <mac address='%02x:%02x:%02x:%02x:%02x:%02x'/>\n",
-                          net->mac[0], net->mac[1], net->mac[2],
-                          net->mac[3], net->mac[4], net->mac[5]);
-
-        switch (net->type) {
-        case QEMUD_NET_NETWORK:
-            virBufferVSprintf(&buf, "      <source network='%s'/>\n", net->dst.network.name);
-
-            if (net->dst.network.ifname[0] != '\0')
-                virBufferVSprintf(&buf, "      <target dev='%s'/>\n", net->dst.network.ifname);
-            break;
-
-        case QEMUD_NET_ETHERNET:
-            if (net->dst.ethernet.ifname[0] != '\0')
-                virBufferVSprintf(&buf, "      <target dev='%s'/>\n", net->dst.ethernet.ifname);
-            if (net->dst.ethernet.script[0] != '\0')
-                virBufferVSprintf(&buf, "      <script path='%s'/>\n", net->dst.ethernet.script);
-            break;
-
-        case QEMUD_NET_BRIDGE:
-            virBufferVSprintf(&buf, "      <source bridge='%s'/>\n", net->dst.bridge.brname);
-            if (net->dst.bridge.ifname[0] != '\0')
-                virBufferVSprintf(&buf, "      <target dev='%s'/>\n", net->dst.bridge.ifname);
-            break;
-
-        case QEMUD_NET_SERVER:
-        case QEMUD_NET_CLIENT:
-        case QEMUD_NET_MCAST:
-            if (net->dst.socket.address[0] != '\0')
-                virBufferVSprintf(&buf, "      <source address='%s' port='%d'/>\n",
-                                  net->dst.socket.address, net->dst.socket.port);
-            else
-                virBufferVSprintf(&buf, "      <source port='%d'/>\n",
-                                  net->dst.socket.port);
-        }
-
-        if (net->model && net->model[0] != '\0') {
-            virBufferVSprintf(&buf, "      <model type='%s'/>\n",
-                              net->model);
-        }
-
-        virBufferAddLit(&buf, "    </interface>\n");
-
-        net = net->next;
-    }
-
-    chr = def->serials;
-    while (chr) {
-        if (qemudGenerateXMLChar(&buf, chr, "serial") < 0)
-            goto no_memory;
-
-        chr = chr->next;
-    }
-
-    chr = def->parallels;
-    while (chr) {
-        if (qemudGenerateXMLChar(&buf, chr, "parallel") < 0)
-            goto no_memory;
-
-        chr = chr->next;
-    }
-
-    /* First serial device is the primary console */
-    if (def->nserials > 0 &&
-        qemudGenerateXMLChar(&buf, def->serials, "console") < 0)
-        goto no_memory;
-
-    input = def->inputs;
-    while (input) {
-        if (input->bus == QEMU_INPUT_BUS_USB)
-            virBufferVSprintf(&buf, "    <input type='%s' bus='usb'/>\n",
-                              input->type == QEMU_INPUT_TYPE_MOUSE ? "mouse" : "tablet");
-        input = input->next;
-    }
-    /* If graphics is enable, add implicit mouse */
-    if (def->graphicsType != QEMUD_GRAPHICS_NONE)
-        virBufferVSprintf(&buf, "    <input type='mouse' bus='%s'/>\n",
-                          STREQ(def->os.type, "hvm") ? "ps2" : "xen");
-
-    switch (def->graphicsType) {
-    case QEMUD_GRAPHICS_VNC:
-        virBufferAddLit(&buf, "    <graphics type='vnc'");
-
-        if (def->vncPort)
-            virBufferVSprintf(&buf, " port='%d'",
-                              qemudIsActiveVM(vm) && live ? def->vncActivePort : def->vncPort);
-
-        if (def->vncListen[0])
-            virBufferVSprintf(&buf, " listen='%s'",
-                              def->vncListen);
-
-        if (def->keymap)
-            virBufferVSprintf(&buf, " keymap='%s'",
-                              def->keymap);
-
-        virBufferAddLit(&buf, "/>\n");
-        break;
-
-    case QEMUD_GRAPHICS_SDL:
-        virBufferAddLit(&buf, "    <graphics type='sdl'/>\n");
-        break;
-
-    case QEMUD_GRAPHICS_NONE:
-    default:
-        break;
-    }
-
-    sound = def->sounds;
-    while(sound) {
-        const char *model = qemudSoundModelToString(sound->model);
-        if (!model) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("invalid sound model"));
-            goto cleanup;
-        }
-        virBufferVSprintf(&buf, "    <sound model='%s'/>\n", model);
-        sound = sound->next;
-    }
-
-    virBufferAddLit(&buf, "  </devices>\n");
-    virBufferAddLit(&buf, "</domain>\n");
-
-    if (virBufferError(&buf))
-        goto no_memory;
-
-    return virBufferContentAndReset(&buf);
-
- no_memory:
-    qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
-                     "%s", _("failed to generate XML: out of memory"));
- cleanup:
-    tmp = virBufferContentAndReset(&buf);
-    VIR_FREE(tmp);
-    return NULL;
-}
-
-
-int qemudDeleteConfig(virConnectPtr conn,
-                      struct qemud_driver *driver ATTRIBUTE_UNUSED,
-                      const char *configFile,
-                      const char *name) {
-    if (!configFile[0]) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         _("no config file for %s"), name);
-        return -1;
-    }
-
-    if (unlink(configFile) < 0) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         _("cannot remove config for %s"), name);
-        return -1;
-    }
-
-    return 0;
-}
-
 #endif /* WITH_QEMU */
index 209330b08ccec23238e388a2cbfb67cb86256dd2..fcd896fd405c05606daf18c926560cce7bde410b 100644 (file)
 #ifdef WITH_QEMU
 
 #include "internal.h"
-#include "bridge.h"
 #include "iptables.h"
+#include "bridge.h"
 #include "capabilities.h"
 #include "network_conf.h"
-#include <netinet/in.h>
-#include <sched.h>
+#include "domain_conf.h"
 
 #define qemudDebug(fmt, ...) do {} while(0)
 
-/* Different types of QEMU acceleration possible */
-enum qemud_vm_virt_type {
-    QEMUD_VIRT_QEMU,
-    QEMUD_VIRT_KQEMU,
-    QEMUD_VIRT_KVM,
-};
-
-/* Two types of disk backends */
-enum qemud_vm_disk_type {
-    QEMUD_DISK_BLOCK,
-    QEMUD_DISK_FILE
-};
-
-/* Three types of disk frontend */
-enum qemud_vm_disk_device {
-    QEMUD_DISK_DISK,
-    QEMUD_DISK_CDROM,
-    QEMUD_DISK_FLOPPY,
-};
-
-enum qemud_vm_disk_bus {
-    QEMUD_DISK_BUS_IDE,
-    QEMUD_DISK_BUS_FDC,
-    QEMUD_DISK_BUS_SCSI,
-    QEMUD_DISK_BUS_VIRTIO,
-    QEMUD_DISK_BUS_XEN,
-
-    QEMUD_DISK_BUS_LAST
-};
-
-/* Stores the virtual disk configuration */
-struct qemud_vm_disk_def {
-    int type;
-    int device;
-    int bus;
-    char src[PATH_MAX];
-    char dst[NAME_MAX];
-    int readonly;
-
-    struct qemud_vm_disk_def *next;
-};
-
-#define QEMUD_MAC_ADDRESS_LEN 6
-#define QEMUD_MODEL_MAX_LEN 10
-#define QEMUD_OS_TYPE_MAX_LEN 10
-#define QEMUD_OS_ARCH_MAX_LEN 10
-#define QEMUD_OS_MACHINE_MAX_LEN 10
-
-/* 5 different types of networking config */
-enum qemud_vm_net_type {
-    QEMUD_NET_USER,
-    QEMUD_NET_ETHERNET,
-    QEMUD_NET_SERVER,
-    QEMUD_NET_CLIENT,
-    QEMUD_NET_MCAST,
-    QEMUD_NET_NETWORK,
-    QEMUD_NET_BRIDGE,
-};
-
-#define QEMUD_MAX_NAME_LEN 50
-#define QEMUD_MAX_XML_LEN 4096
-#define QEMUD_MAX_ERROR_LEN 1024
 #define QEMUD_CPUMASK_LEN CPU_SETSIZE
 
-/* Stores the virtual network interface configuration */
-struct qemud_vm_net_def {
-    int type;
-    unsigned char mac[QEMUD_MAC_ADDRESS_LEN];
-    char model[QEMUD_MODEL_MAX_LEN];
-    union {
-        struct {
-            char ifname[BR_IFNAME_MAXLEN];
-            char script[PATH_MAX];
-        } ethernet;
-        struct {
-            char address[BR_INET_ADDR_MAXLEN];
-            int port;
-        } socket; /* any of NET_CLIENT or NET_SERVER or NET_MCAST */
-        struct {
-            char name[QEMUD_MAX_NAME_LEN];
-            char ifname[BR_IFNAME_MAXLEN];
-        } network;
-        struct {
-            char brname[BR_IFNAME_MAXLEN];
-            char ifname[BR_IFNAME_MAXLEN];
-        } bridge;
-    } dst;
-
-    struct qemud_vm_net_def *next;
-};
-
-enum qemu_vm_chr_dst_type {
-    QEMUD_CHR_SRC_TYPE_NULL,
-    QEMUD_CHR_SRC_TYPE_VC,
-    QEMUD_CHR_SRC_TYPE_PTY,
-    QEMUD_CHR_SRC_TYPE_DEV,
-    QEMUD_CHR_SRC_TYPE_FILE,
-    QEMUD_CHR_SRC_TYPE_PIPE,
-    QEMUD_CHR_SRC_TYPE_STDIO,
-    QEMUD_CHR_SRC_TYPE_UDP,
-    QEMUD_CHR_SRC_TYPE_TCP,
-    QEMUD_CHR_SRC_TYPE_UNIX,
-
-    QEMUD_CHR_SRC_TYPE_LAST,
-};
-
-enum {
-    QEMUD_CHR_SRC_TCP_PROTOCOL_RAW,
-    QEMUD_CHR_SRC_TCP_PROTOCOL_TELNET,
-};
-
-struct qemud_vm_chr_def {
-    int dstPort;
-
-    int srcType;
-    union {
-        struct {
-            char path[PATH_MAX];
-        } file; /* pty, file, pipe, or device */
-        struct {
-            char host[BR_INET_ADDR_MAXLEN];
-            char service[BR_INET_ADDR_MAXLEN];
-            int listen;
-            int protocol;
-        } tcp;
-        struct {
-            char bindHost[BR_INET_ADDR_MAXLEN];
-            char bindService[BR_INET_ADDR_MAXLEN];
-            char connectHost[BR_INET_ADDR_MAXLEN];
-            char connectService[BR_INET_ADDR_MAXLEN];
-        } udp;
-        struct {
-            char path[PATH_MAX];
-            int listen;
-        } nix;
-    } srcData;
-
-    struct qemud_vm_chr_def *next;
-};
-
-enum qemu_vm_input_type {
-    QEMU_INPUT_TYPE_MOUSE,
-    QEMU_INPUT_TYPE_TABLET,
-};
-
-enum qemu_vm_input_bus {
-    QEMU_INPUT_BUS_PS2,
-    QEMU_INPUT_BUS_USB,
-    QEMU_INPUT_BUS_XEN,
-};
-
-struct qemud_vm_input_def {
-    int type;
-    int bus;
-    struct qemud_vm_input_def *next;
-};
-
-enum qemu_vm_sound_model {
-    QEMU_SOUND_NONE   = 0,
-    QEMU_SOUND_SB16,
-    QEMU_SOUND_ES1370,
-    QEMU_SOUND_PCSPK,
-};
-
-struct qemud_vm_sound_def {
-    int model;
-    struct qemud_vm_sound_def *next;
-};
-
-/* Flags for the 'type' field in next struct */
-enum qemud_vm_device_type {
-    QEMUD_DEVICE_DISK,
-    QEMUD_DEVICE_NET,
-    QEMUD_DEVICE_INPUT,
-    QEMUD_DEVICE_SOUND,
-};
-
-struct qemud_vm_device_def {
-    int type;
-    union {
-        struct qemud_vm_disk_def disk;
-        struct qemud_vm_net_def net;
-        struct qemud_vm_input_def input;
-        struct qemud_vm_sound_def sound;
-    } data;
-};
-
-#define QEMUD_MAX_BOOT_DEVS 4
-
-/* 3 possible boot devices */
-enum qemud_vm_boot_order {
-    QEMUD_BOOT_FLOPPY,
-    QEMUD_BOOT_CDROM,
-    QEMUD_BOOT_DISK,
-    QEMUD_BOOT_NET,
-};
-/* 3 possible graphics console modes */
-enum qemud_vm_graphics_type {
-    QEMUD_GRAPHICS_NONE,
-    QEMUD_GRAPHICS_SDL,
-    QEMUD_GRAPHICS_VNC,
-};
-
 /* Internal flags to keep track of qemu command line capabilities */
 enum qemud_cmd_flags {
     QEMUD_CMD_FLAG_KQEMU          = (1 << 0),
@@ -251,107 +49,12 @@ enum qemud_cmd_flags {
     QEMUD_CMD_FLAG_NAME           = (1 << 5),
 };
 
-
-enum qemud_vm_features {
-    QEMUD_FEATURE_ACPI = 1,
-};
-
-/* Operating system configuration data & machine / arch */
-struct qemud_vm_os_def {
-    char type[QEMUD_OS_TYPE_MAX_LEN];
-    char arch[QEMUD_OS_ARCH_MAX_LEN];
-    char machine[QEMUD_OS_MACHINE_MAX_LEN];
-    int nBootDevs;
-    int bootDevs[QEMUD_MAX_BOOT_DEVS];
-    char kernel[PATH_MAX];
-    char initrd[PATH_MAX];
-    char cmdline[PATH_MAX];
-    char binary[PATH_MAX];
-    char bootloader[PATH_MAX];
-};
-
-/* Guest VM main configuration */
-struct qemud_vm_def {
-    int virtType;
-    unsigned char uuid[VIR_UUID_BUFLEN];
-    char name[QEMUD_MAX_NAME_LEN];
-
-    unsigned long memory;
-    unsigned long maxmem;
-    int vcpus;
-    char cpumask[QEMUD_CPUMASK_LEN];
-
-    int noReboot;
-
-    struct qemud_vm_os_def os;
-
-    int localtime;
-    int features;
-    int graphicsType;
-    int vncPort;
-    int vncActivePort;
-    char vncListen[BR_INET_ADDR_MAXLEN];
-    char *keymap;
-
-    unsigned int ndisks;
-    struct qemud_vm_disk_def *disks;
-
-    unsigned int nnets;
-    struct qemud_vm_net_def *nets;
-
-    unsigned int ninputs;
-    struct qemud_vm_input_def *inputs;
-
-    unsigned int nsounds;
-    struct qemud_vm_sound_def *sounds;
-
-    unsigned int nserials;
-    struct qemud_vm_chr_def *serials;
-
-    unsigned int nparallels;
-    struct qemud_vm_chr_def *parallels;
-};
-
-/* Guest VM runtime state */
-struct qemud_vm {
-    int stdin;
-    int stdout;
-    int stderr;
-    int monitor;
-    int logfile;
-    int pid;
-    int id;
-    int state;
-
-    int *tapfds;
-    int ntapfds;
-
-    int nvcpupids;
-    int *vcpupids;
-
-    int qemuVersion;
-    int qemuCmdFlags; /* values from enum qemud_cmd_flags */
-
-    char configFile[PATH_MAX];
-    char autostartLink[PATH_MAX];
-    char migrateFrom[PATH_MAX];
-
-    struct qemud_vm_def *def; /* The current definition */
-    struct qemud_vm_def *newDef; /* New definition to activate at shutdown */
-
-    unsigned int autostart : 1;
-
-    struct qemud_vm *next;
-};
-
 /* Main driver state */
 struct qemud_driver {
     int qemuVersion;
-    int nactivevms;
-    int ninactivevms;
-    struct qemud_vm *vms;
     int nextvmid;
 
+    virDomainObjPtr domains;
     virNetworkObjPtr networks;
 
     brControl *brctl;
@@ -360,22 +63,16 @@ struct qemud_driver {
     char *autostartDir;
     char *networkConfigDir;
     char *networkAutostartDir;
-    char logDir[PATH_MAX];
+    char *logDir;
     unsigned int vncTLS : 1;
     unsigned int vncTLSx509verify : 1;
     char *vncTLSx509certdir;
-    char vncListen[BR_INET_ADDR_MAXLEN];
+    char *vncListen;
 
     virCapsPtr caps;
 };
 
 
-static inline int
-qemudIsActiveVM(const struct qemud_vm *vm)
-{
-    return vm->id != -1;
-}
-
 void qemudReportError(virConnectPtr conn,
                       virDomainPtr dom,
                       virNetworkPtr net,
@@ -386,57 +83,22 @@ void qemudReportError(virConnectPtr conn,
 int qemudLoadDriverConfig(struct qemud_driver *driver,
                           const char *filename);
 
-struct qemud_vm *qemudFindVMByID(const struct qemud_driver *driver,
-                                 int id);
-struct qemud_vm *qemudFindVMByUUID(const struct qemud_driver *driver,
-                                   const unsigned char *uuid);
-struct qemud_vm *qemudFindVMByName(const struct qemud_driver *driver,
-                                   const char *name);
-
 virCapsPtr  qemudCapsInit               (void);
 
 int         qemudExtractVersion         (virConnectPtr conn,
                                          struct qemud_driver *driver);
-int         qemudBuildCommandLine       (virConnectPtr conn,
-                                         struct qemud_driver *driver,
-                                         struct qemud_vm *vm,
-                                         char ***argv);
-
-int         qemudScanConfigs            (struct qemud_driver *driver);
-int         qemudDeleteConfig           (virConnectPtr conn,
-                                         struct qemud_driver *driver,
-                                         const char *configFile,
-                                         const char *name);
-
-void        qemudFreeVMDef              (struct qemud_vm_def *vm);
-void        qemudFreeVM                 (struct qemud_vm *vm);
-
-struct qemud_vm *
-            qemudAssignVMDef            (virConnectPtr conn,
-                                         struct qemud_driver *driver,
-                                         struct qemud_vm_def *def);
-void        qemudRemoveInactiveVM       (struct qemud_driver *driver,
-                                         struct qemud_vm *vm);
-
-struct qemud_vm_device_def *
-            qemudParseVMDeviceDef       (virConnectPtr conn,
-                                         const struct qemud_vm_def *def,
-                                         const char *xmlStr);
+int         qemudExtractVersionInfo     (const char *qemu,
+                                         int *version,
+                                         int *flags);
 
-struct qemud_vm_def *
-            qemudParseVMDef             (virConnectPtr conn,
-                                         struct qemud_driver *driver,
-                                         const char *xmlStr,
-                                         const char *displayName);
-int         qemudSaveVMDef              (virConnectPtr conn,
-                                         struct qemud_driver *driver,
-                                         struct qemud_vm *vm,
-                                         struct qemud_vm_def *def);
-char *      qemudGenerateXML            (virConnectPtr conn,
+int         qemudBuildCommandLine       (virConnectPtr conn,
                                          struct qemud_driver *driver,
-                                         struct qemud_vm *vm,
-                                         struct qemud_vm_def *def,
-                                         int live);
+                                         virDomainObjPtr dom,
+                                         int qemuCmdFlags,
+                                         char ***argv,
+                                         int **tapfds,
+                                         int *ntapfds,
+                                         const char *migrateFrom);
 
 const char *qemudVirtTypeToString       (int type);
 
index 26853d1f20345391ffee6d2c5d202f27b85dd1f8..3d0b6c5114b50f3103d0f1c409b1114429306715 100644 (file)
@@ -44,7 +44,6 @@
 #include <pwd.h>
 #include <stdio.h>
 #include <sys/wait.h>
-#include <libxml/uri.h>
 
 #if HAVE_NUMACTL
 #include <numa.h>
 #include <sched.h>
 #endif
 
-#include "internal.h"
+#include "qemu_driver.h"
+#include "qemu_conf.h"
 #include "c-ctype.h"
 #include "event.h"
 #include "buf.h"
 #include "util.h"
-#include "qemu_driver.h"
-#include "qemu_conf.h"
 #include "nodeinfo.h"
 #include "stats_linux.h"
 #include "capabilities.h"
@@ -112,11 +110,12 @@ static int qemudSetNonBlock(int fd) {
 static void qemudDispatchVMEvent(int fd, int events, void *opaque);
 static int qemudStartVMDaemon(virConnectPtr conn,
                               struct qemud_driver *driver,
-                              struct qemud_vm *vm);
+                              virDomainObjPtr vm,
+                              const char *migrateFrom);
 
 static void qemudShutdownVMDaemon(virConnectPtr conn,
                                   struct qemud_driver *driver,
-                                  struct qemud_vm *vm);
+                                  virDomainObjPtr vm);
 
 static int qemudStartNetworkDaemon(virConnectPtr conn,
                                    struct qemud_driver *driver,
@@ -128,7 +127,7 @@ static int qemudShutdownNetworkDaemon(virConnectPtr conn,
 
 static int qemudDomainGetMaxVcpus(virDomainPtr dom);
 static int qemudMonitorCommand (const struct qemud_driver *driver,
-                                const struct qemud_vm *vm,
+                                const virDomainObjPtr vm,
                                 const char *cmd,
                                 char **reply);
 
@@ -138,7 +137,7 @@ static struct qemud_driver *qemu_driver = NULL;
 static
 void qemudAutostartConfigs(struct qemud_driver *driver) {
     virNetworkObjPtr network;
-    struct qemud_vm *vm;
+    virDomainObjPtr vm;
 
     network = driver->networks;
     while (network != NULL) {
@@ -155,13 +154,13 @@ void qemudAutostartConfigs(struct qemud_driver *driver) {
         network = next;
     }
 
-    vm = driver->vms;
+    vm = driver->domains;
     while (vm != NULL) {
-        struct qemud_vm *next = vm->next;
+        virDomainObjPtr next = vm->next;
 
         if (vm->autostart &&
-            !qemudIsActiveVM(vm) &&
-            qemudStartVMDaemon(NULL, driver, vm) < 0) {
+            !virDomainIsActive(vm) &&
+            qemudStartVMDaemon(NULL, driver, vm, NULL) < 0) {
             virErrorPtr err = virGetLastError();
             qemudLog(QEMUD_ERR, _("Failed to autostart VM '%s': %s"),
                      vm->def->name, err->message);
@@ -191,8 +190,9 @@ qemudStartup(void) {
     qemu_driver->nextvmid = 1;
 
     if (!uid) {
-        if (snprintf(qemu_driver->logDir, PATH_MAX, "%s/log/libvirt/qemu", LOCAL_STATE_DIR) >= PATH_MAX)
-            goto snprintf_error;
+        if (asprintf(&qemu_driver->logDir,
+                     "%s/log/libvirt/qemu", LOCAL_STATE_DIR) == -1)
+            goto out_of_memory;
 
         if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
             goto out_of_memory;
@@ -203,8 +203,9 @@ qemudStartup(void) {
             goto out_of_memory;
         }
 
-        if (snprintf(qemu_driver->logDir, PATH_MAX, "%s/.libvirt/qemu/log", pw->pw_dir) >= PATH_MAX)
-            goto snprintf_error;
+        if (asprintf(&qemu_driver->logDir,
+                     "%s/.libvirt/qemu/log", pw->pw_dir) == -1)
+            goto out_of_memory;
 
         if (asprintf (&base, "%s/.libvirt", pw->pw_dir) == -1) {
             qemudLog (QEMUD_ERR,
@@ -243,7 +244,11 @@ qemudStartup(void) {
         return -1;
     }
 
-    if (qemudScanConfigs(qemu_driver) < 0) {
+    if (virDomainLoadAllConfigs(NULL,
+                                qemu_driver->caps,
+                                &qemu_driver->domains,
+                                qemu_driver->configDir,
+                                qemu_driver->autostartDir) < 0) {
         qemudShutdown();
         return -1;
     }
@@ -258,11 +263,6 @@ qemudStartup(void) {
 
     return 0;
 
- snprintf_error:
-    qemudLog(QEMUD_ERR,
-             "%s", _("Resulting path to long for buffer in qemudInitPaths()"));
-    return -1;
-
  out_of_memory:
     qemudLog (QEMUD_ERR,
               "%s", _("qemudStartup: out of memory"));
@@ -279,7 +279,12 @@ qemudStartup(void) {
  */
 static int
 qemudReload(void) {
-    qemudScanConfigs(qemu_driver);
+    virDomainLoadAllConfigs(NULL,
+                            qemu_driver->caps,
+                            &qemu_driver->domains,
+                            qemu_driver->configDir,
+                            qemu_driver->autostartDir);
+
     virNetworkLoadAllConfigs(NULL,
                              &qemu_driver->networks,
                              qemu_driver->networkConfigDir,
@@ -306,16 +311,20 @@ qemudReload(void) {
  */
 static int
 qemudActive(void) {
+    virDomainObjPtr dom = qemu_driver->domains;
     virNetworkObjPtr net = qemu_driver->networks;
+    while (dom) {
+        if (virDomainIsActive(dom))
+            return 1;
+        dom = dom->next;
+    }
+
     while (net) {
-        if (net->active)
+        if (virNetworkIsActive(net))
             return 1;
         net = net->next;
     }
 
-    if (qemu_driver->nactivevms)
-        return 1;
-
     /* Otherwise we're happy to deal with a shutdown */
     return 0;
 }
@@ -327,7 +336,7 @@ qemudActive(void) {
  */
 static int
 qemudShutdown(void) {
-    struct qemud_vm *vm;
+    virDomainObjPtr vm;
     virNetworkObjPtr network;
 
     if (!qemu_driver)
@@ -336,26 +345,25 @@ qemudShutdown(void) {
     virCapabilitiesFree(qemu_driver->caps);
 
     /* shutdown active VMs */
-    vm = qemu_driver->vms;
+    vm = qemu_driver->domains;
     while (vm) {
-        struct qemud_vm *next = vm->next;
-        if (qemudIsActiveVM(vm))
+        virDomainObjPtr next = vm->next;
+        if (virDomainIsActive(vm))
             qemudShutdownVMDaemon(NULL, qemu_driver, vm);
-        if (!vm->configFile[0])
-            qemudRemoveInactiveVM(qemu_driver, vm);
+        if (!vm->configFile)
+            virDomainRemoveInactive(&qemu_driver->domains,
+                                    vm);
         vm = next;
     }
 
     /* free inactive VMs */
-    vm = qemu_driver->vms;
+    vm = qemu_driver->domains;
     while (vm) {
-        struct qemud_vm *next = vm->next;
-        qemudFreeVM(vm);
+        virDomainObjPtr next = vm->next;
+        virDomainObjFree(vm);
         vm = next;
     }
-    qemu_driver->vms = NULL;
-    qemu_driver->nactivevms = 0;
-    qemu_driver->ninactivevms = 0;
+    qemu_driver->domains = NULL;
 
     /* shutdown active networks */
     network = qemu_driver->networks;
@@ -375,6 +383,7 @@ qemudShutdown(void) {
     }
     qemu_driver->networks = NULL;
 
+    VIR_FREE(qemu_driver->logDir);
     VIR_FREE(qemu_driver->configDir);
     VIR_FREE(qemu_driver->autostartDir);
     VIR_FREE(qemu_driver->networkConfigDir);
@@ -395,14 +404,14 @@ qemudShutdown(void) {
 /* Return -1 for error, 1 to continue reading and 0 for success */
 typedef int qemudHandlerMonitorOutput(virConnectPtr conn,
                                       struct qemud_driver *driver,
-                                      struct qemud_vm *vm,
+                                      virDomainObjPtr vm,
                                       const char *output,
                                       int fd);
 
 static int
 qemudReadMonitorOutput(virConnectPtr conn,
                        struct qemud_driver *driver,
-                       struct qemud_vm *vm,
+                       virDomainObjPtr vm,
                        int fd,
                        char *buf,
                        int buflen,
@@ -475,7 +484,7 @@ qemudReadMonitorOutput(virConnectPtr conn,
 static int
 qemudCheckMonitorPrompt(virConnectPtr conn ATTRIBUTE_UNUSED,
                         struct qemud_driver *driver ATTRIBUTE_UNUSED,
-                        struct qemud_vm *vm,
+                        virDomainObjPtr vm,
                         const char *output,
                         int fd)
 {
@@ -489,7 +498,7 @@ qemudCheckMonitorPrompt(virConnectPtr conn ATTRIBUTE_UNUSED,
 
 static int qemudOpenMonitor(virConnectPtr conn,
                             struct qemud_driver *driver,
-                            struct qemud_vm *vm,
+                            virDomainObjPtr vm,
                             const char *monitor) {
     int monfd;
     char buf[1024];
@@ -526,33 +535,36 @@ static int qemudOpenMonitor(virConnectPtr conn,
     return ret;
 }
 
-static int qemudExtractMonitorPath(const char *haystack,
+static int qemudExtractMonitorPath(virConnectPtr conn,
+                                   const char *haystack,
                                    size_t *offset,
-                                   char *path, int pathmax) {
+                                   char **path) {
     static const char needle[] = "char device redirected to";
-    char *tmp;
+    char *tmp, *dev;
 
+    VIR_FREE(*path);
     /* First look for our magic string */
-    if (!(tmp = strstr(haystack + *offset, needle)))
-        return -1;
-
-    /* Grab all the trailing data */
-    strncpy(path, tmp+sizeof(needle), pathmax-1);
-    path[pathmax-1] = '\0';
-
-    /* Update offset to point to where we found the needle..*/
-    *offset = tmp - haystack;
+    if (!(tmp = strstr(haystack + *offset, needle))) {
+        return 1;
+    }
+    tmp += sizeof(needle);
+    dev = tmp;
 
     /*
      * And look for first whitespace character and nul terminate
      * to mark end of the pty path
      */
-    tmp = path;
     while (*tmp) {
         if (c_isspace(*tmp)) {
-            *tmp = '\0';
+            if (VIR_ALLOC_N(*path, (tmp-dev)+1) < 0) {
+                qemudReportError(conn, NULL, NULL,
+                                 VIR_ERR_NO_MEMORY, NULL);
+                return -1;
+            }
+            strncpy(*path, dev, (tmp-dev));
+            (*path)[(tmp-dev)] = '\0';
             /* ... now further update offset till we get EOL */
-            *offset += (sizeof(needle)-1) + strlen(path);
+            *offset += tmp - haystack;
             return 0;
         }
         tmp++;
@@ -564,19 +576,20 @@ static int qemudExtractMonitorPath(const char *haystack,
      * least see a \n - indicate that we want to carry
      * on trying again
      */
-    return -1;
+    return 1;
 }
 
 static int
 qemudFindCharDevicePTYs(virConnectPtr conn,
                         struct qemud_driver *driver,
-                        struct qemud_vm *vm,
+                        virDomainObjPtr vm,
                         const char *output,
                         int fd ATTRIBUTE_UNUSED)
 {
-    char monitor[PATH_MAX];
+    char *monitor = NULL;
     size_t offset = 0;
-    struct qemud_vm_chr_def *chr;
+    virDomainChrDefPtr chr;
+    int ret;
 
     /* The order in which QEMU prints out the PTY paths is
        the order in which it procsses its monitor, serial
@@ -584,17 +597,16 @@ qemudFindCharDevicePTYs(virConnectPtr conn,
        ordering.... */
 
     /* So first comes the monitor device */
-    if (qemudExtractMonitorPath(output, &offset, monitor, sizeof(monitor)) < 0)
-        return 1; /* keep reading */
+    if ((ret = qemudExtractMonitorPath(conn, output, &offset, &monitor)) != 0)
+        goto cleanup;
 
     /* then the serial devices */
     chr = vm->def->serials;
     while (chr) {
-        if (chr->srcType == QEMUD_CHR_SRC_TYPE_PTY) {
-            if (qemudExtractMonitorPath(output, &offset,
-                                        chr->srcData.file.path,
-                                        sizeof(chr->srcData.file.path)) < 0)
-                return 1; /* keep reading */
+        if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
+            if ((ret = qemudExtractMonitorPath(conn, output, &offset,
+                                               &chr->data.file.path)) != 0)
+                goto cleanup;
         }
         chr = chr->next;
     }
@@ -602,22 +614,25 @@ qemudFindCharDevicePTYs(virConnectPtr conn,
     /* and finally the parallel devices */
     chr = vm->def->parallels;
     while (chr) {
-        if (chr->srcType == QEMUD_CHR_SRC_TYPE_PTY) {
-            if (qemudExtractMonitorPath(output, &offset,
-                                        chr->srcData.file.path,
-                                        sizeof(chr->srcData.file.path)) < 0)
-                return 1; /* keep reading */
+        if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
+            if ((ret = qemudExtractMonitorPath(conn, output, &offset,
+                                               &chr->data.file.path)) != 0)
+                goto cleanup;
         }
         chr = chr->next;
     }
 
     /* Got them all, so now open the monitor console */
-    return qemudOpenMonitor(conn, driver, vm, monitor);
+    ret = qemudOpenMonitor(conn, driver, vm, monitor);
+
+cleanup:
+    VIR_FREE(monitor);
+    return ret;
 }
 
 static int qemudWaitForMonitor(virConnectPtr conn,
                                struct qemud_driver *driver,
-                               struct qemud_vm *vm) {
+                               virDomainObjPtr vm) {
     char buf[1024]; /* Plenty of space to get startup greeting */
     int ret = qemudReadMonitorOutput(conn,
                                      driver, vm, vm->stderr,
@@ -638,14 +653,14 @@ static int qemudWaitForMonitor(virConnectPtr conn,
 static int
 qemudDetectVcpuPIDs(virConnectPtr conn,
                     struct qemud_driver *driver,
-                    struct qemud_vm *vm) {
+                    virDomainObjPtr vm) {
     char *qemucpus = NULL;
     char *line;
     int lastVcpu = -1;
 
     /* Only KVM has seperate threads for CPUs,
        others just use main QEMU process for CPU */
-    if (vm->def->virtType != QEMUD_VIRT_KVM)
+    if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM)
         vm->nvcpupids = 1;
     else
         vm->nvcpupids = vm->def->vcpus;
@@ -656,7 +671,7 @@ qemudDetectVcpuPIDs(virConnectPtr conn,
         return -1;
     }
 
-    if (vm->def->virtType != QEMUD_VIRT_KVM) {
+    if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM) {
         vm->vcpupids[0] = vm->pid;
         return 0;
     }
@@ -738,7 +753,7 @@ error:
 static int
 qemudInitCpus(virConnectPtr conn,
               struct qemud_driver *driver,
-              struct qemud_vm *vm) {
+              virDomainObjPtr vm) {
     char *info = NULL;
 #if HAVE_SCHED_GETAFFINITY
     cpu_set_t mask;
@@ -819,28 +834,33 @@ static int qemudNextFreeVNCPort(struct qemud_driver *driver ATTRIBUTE_UNUSED) {
 
 static int qemudStartVMDaemon(virConnectPtr conn,
                               struct qemud_driver *driver,
-                              struct qemud_vm *vm) {
+                              virDomainObjPtr vm,
+                              const char *migrateFrom) {
     char **argv = NULL, **tmp;
     int i, ret;
     char logfile[PATH_MAX];
     struct stat sb;
+    int *tapfds = NULL;
+    int ntapfds = 0;
+    int qemuCmdFlags;
 
-    if (qemudIsActiveVM(vm)) {
+    if (virDomainIsActive(vm)) {
         qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                          "%s", _("VM is already active"));
         return -1;
     }
 
-    if (vm->def->vncPort < 0) {
+    if (vm->def->graphics &&
+        vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
+        vm->def->graphics->data.vnc.autoport) {
         int port = qemudNextFreeVNCPort(driver);
         if (port < 0) {
             qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                              "%s", _("Unable to find an unused VNC port"));
             return -1;
         }
-        vm->def->vncActivePort = port;
-    } else
-        vm->def->vncActivePort = vm->def->vncPort;
+        vm->def->graphics->data.vnc.port = port;
+    }
 
     if ((strlen(driver->logDir) + /* path */
          1 + /* Separator */
@@ -884,16 +904,26 @@ static int qemudStartVMDaemon(virConnectPtr conn,
      * Technically we could catch the exec() failure, but that's
      * in a sub-process so its hard to feed back a useful error
      */
-    if (stat(vm->def->os.binary, &sb) < 0) {
+    if (stat(vm->def->emulator, &sb) < 0) {
         qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                          _("Cannot find QEMU binary %s: %s"),
-                         vm->def->os.binary,
+                         vm->def->emulator,
                          strerror(errno));
         return -1;
     }
 
+    if (qemudExtractVersionInfo(vm->def->emulator,
+                                NULL,
+                                &qemuCmdFlags) < 0) {
+        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                         _("Cannot determine QEMU argv syntax %s"),
+                         vm->def->emulator);
+        return -1;
+    }
 
-    if (qemudBuildCommandLine(conn, driver, vm, &argv) < 0) {
+    if (qemudBuildCommandLine(conn, driver, vm,
+                              qemuCmdFlags, &argv,
+                              &tapfds, &ntapfds, migrateFrom) < 0) {
         close(vm->logfile);
         vm->logfile = -1;
         return -1;
@@ -916,24 +946,19 @@ static int qemudStartVMDaemon(virConnectPtr conn,
     ret = virExecNonBlock(conn, argv, &vm->pid,
                           vm->stdin, &vm->stdout, &vm->stderr);
     if (ret == 0) {
-        vm->id = driver->nextvmid++;
-        vm->state = vm->migrateFrom[0] ? VIR_DOMAIN_PAUSED : VIR_DOMAIN_RUNNING;
-
-        driver->ninactivevms--;
-        driver->nactivevms++;
+        vm->def->id = driver->nextvmid++;
+        vm->state = migrateFrom ? VIR_DOMAIN_PAUSED : VIR_DOMAIN_RUNNING;
     }
 
     for (i = 0 ; argv[i] ; i++)
         VIR_FREE(argv[i]);
     VIR_FREE(argv);
 
-    if (vm->tapfds) {
-        for (i = 0; vm->tapfds[i] != -1; i++) {
-            close(vm->tapfds[i]);
-            vm->tapfds[i] = -1;
+    if (tapfds) {
+        for (i = 0 ; i < ntapfds ; i++) {
+            close(tapfds[i]);
         }
-        VIR_FREE(vm->tapfds);
-        vm->ntapfds = 0;
+        VIR_FREE(tapfds);
     }
 
     if (ret == 0) {
@@ -957,7 +982,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
 }
 
 static int qemudVMData(struct qemud_driver *driver ATTRIBUTE_UNUSED,
-                       struct qemud_vm *vm, int fd) {
+                       virDomainObjPtr vm, int fd) {
     char buf[4096];
     if (vm->pid < 0)
         return 0;
@@ -986,8 +1011,8 @@ static int qemudVMData(struct qemud_driver *driver ATTRIBUTE_UNUSED,
 
 
 static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
-                                  struct qemud_driver *driver, struct qemud_vm *vm) {
-    if (!qemudIsActiveVM(vm))
+                                  struct qemud_driver *driver, virDomainObjPtr vm) {
+    if (!virDomainIsActive(vm))
         return;
 
     qemudLog(QEMUD_INFO, _("Shutting down VM '%s'"), vm->def->name);
@@ -1021,35 +1046,35 @@ static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
     }
 
     vm->pid = -1;
-    vm->id = -1;
+    vm->def->id = -1;
     vm->state = VIR_DOMAIN_SHUTOFF;
     VIR_FREE(vm->vcpupids);
     vm->nvcpupids = 0;
 
     if (vm->newDef) {
-        qemudFreeVMDef(vm->def);
+        virDomainDefFree(vm->def);
         vm->def = vm->newDef;
+        vm->def->id = -1;
         vm->newDef = NULL;
     }
-
-    driver->nactivevms--;
-    driver->ninactivevms++;
 }
 
-static int qemudDispatchVMLog(struct qemud_driver *driver, struct qemud_vm *vm, int fd) {
+static int qemudDispatchVMLog(struct qemud_driver *driver, virDomainObjPtr vm, int fd) {
     if (qemudVMData(driver, vm, fd) < 0) {
         qemudShutdownVMDaemon(NULL, driver, vm);
-        if (!vm->configFile[0])
-            qemudRemoveInactiveVM(driver, vm);
+        if (!vm->configFile)
+            virDomainRemoveInactive(&driver->domains,
+                                    vm);
     }
     return 0;
 }
 
-static int qemudDispatchVMFailure(struct qemud_driver *driver, struct qemud_vm *vm,
+static int qemudDispatchVMFailure(struct qemud_driver *driver, virDomainObjPtr vm,
                                   int fd ATTRIBUTE_UNUSED) {
     qemudShutdownVMDaemon(NULL, driver, vm);
-    if (!vm->configFile[0])
-        qemudRemoveInactiveVM(driver, vm);
+    if (!vm->configFile)
+        virDomainRemoveInactive(&driver->domains,
+                                vm);
     return 0;
 }
 
@@ -1579,10 +1604,10 @@ static int qemudShutdownNetworkDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
 
 static void qemudDispatchVMEvent(int fd, int events, void *opaque) {
     struct qemud_driver *driver = (struct qemud_driver *)opaque;
-    struct qemud_vm *vm = driver->vms;
+    virDomainObjPtr vm = driver->domains;
 
     while (vm) {
-        if (qemudIsActiveVM(vm) &&
+        if (virDomainIsActive(vm) &&
             (vm->stdout == fd ||
              vm->stderr == fd))
             break;
@@ -1601,7 +1626,7 @@ static void qemudDispatchVMEvent(int fd, int events, void *opaque) {
 
 static int
 qemudMonitorCommand (const struct qemud_driver *driver ATTRIBUTE_UNUSED,
-                     const struct qemud_vm *vm,
+                     const virDomainObjPtr vm,
                      const char *cmd,
                      char **reply) {
     int size = 0;
@@ -1871,9 +1896,9 @@ static int qemudGetProcessInfo(unsigned long long *cpuTime, int pid) {
 
 
 static virDomainPtr qemudDomainLookupByID(virConnectPtr conn,
-                                   int id) {
+                                          int id) {
     struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByID(driver, id);
+    virDomainObjPtr vm = virDomainFindByID(driver->domains, id);
     virDomainPtr dom;
 
     if (!vm) {
@@ -1882,13 +1907,13 @@ static virDomainPtr qemudDomainLookupByID(virConnectPtr conn,
     }
 
     dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
-    if (dom) dom->id = vm->id;
+    if (dom) dom->id = vm->def->id;
     return dom;
 }
 static virDomainPtr qemudDomainLookupByUUID(virConnectPtr conn,
-                                     const unsigned char *uuid) {
+                                            const unsigned char *uuid) {
     struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByUUID(driver, uuid);
+    virDomainObjPtr vm = virDomainFindByUUID(driver->domains, uuid);
     virDomainPtr dom;
 
     if (!vm) {
@@ -1897,13 +1922,13 @@ static virDomainPtr qemudDomainLookupByUUID(virConnectPtr conn,
     }
 
     dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
-    if (dom) dom->id = vm->id;
+    if (dom) dom->id = vm->def->id;
     return dom;
 }
 static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
-                                     const char *name) {
+                                            const char *name) {
     struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByName(driver, name);
+    virDomainObjPtr vm = virDomainFindByName(driver->domains, name);
     virDomainPtr dom;
 
     if (!vm) {
@@ -1912,7 +1937,7 @@ static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
     }
 
     dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
-    if (dom) dom->id = vm->id;
+    if (dom) dom->id = vm->def->id;
     return dom;
 }
 
@@ -1949,11 +1974,11 @@ qemudGetHostname (virConnectPtr conn)
 
 static int qemudListDomains(virConnectPtr conn, int *ids, int nids) {
     struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
-    struct qemud_vm *vm = driver->vms;
+    virDomainObjPtr vm = driver->domains;
     int got = 0;
     while (vm && got < nids) {
-        if (qemudIsActiveVM(vm)) {
-            ids[got] = vm->id;
+        if (virDomainIsActive(vm)) {
+            ids[got] = vm->def->id;
             got++;
         }
         vm = vm->next;
@@ -1962,30 +1987,40 @@ static int qemudListDomains(virConnectPtr conn, int *ids, int nids) {
 }
 static int qemudNumDomains(virConnectPtr conn) {
     struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
-    return driver->nactivevms;
+    int n = 0;
+    virDomainObjPtr dom = driver->domains;
+    while (dom) {
+        if (virDomainIsActive(dom))
+            n++;
+        dom = dom->next;
+    }
+    return n;
 }
 static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
                                       unsigned int flags ATTRIBUTE_UNUSED) {
-    struct qemud_vm_def *def;
-    struct qemud_vm *vm;
+    virDomainDefPtr def;
+    virDomainObjPtr vm;
     virDomainPtr dom;
     struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
 
-    if (!(def = qemudParseVMDef(conn, driver, xml, NULL)))
+    if (!(def = virDomainDefParseString(conn, driver->caps, xml)))
         return NULL;
 
-    if (!(vm = qemudAssignVMDef(conn, driver, def))) {
-        qemudFreeVMDef(def);
+    if (!(vm = virDomainAssignDef(conn,
+                                  &driver->domains,
+                                  def))) {
+        virDomainDefFree(def);
         return NULL;
     }
 
-    if (qemudStartVMDaemon(conn, driver, vm) < 0) {
-        qemudRemoveInactiveVM(driver, vm);
+    if (qemudStartVMDaemon(conn, driver, vm, NULL) < 0) {
+        virDomainRemoveInactive(&driver->domains,
+                                vm);
         return NULL;
     }
 
     dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
-    if (dom) dom->id = vm->id;
+    if (dom) dom->id = vm->def->id;
     return dom;
 }
 
@@ -1993,12 +2028,12 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
 static int qemudDomainSuspend(virDomainPtr dom) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
     char *info;
-    struct qemud_vm *vm = qemudFindVMByID(driver, dom->id);
+    virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id);
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id);
         return -1;
     }
-    if (!qemudIsActiveVM(vm)) {
+    if (!virDomainIsActive(vm)) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("domain is not running"));
         return -1;
@@ -2021,13 +2056,13 @@ static int qemudDomainSuspend(virDomainPtr dom) {
 static int qemudDomainResume(virDomainPtr dom) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
     char *info;
-    struct qemud_vm *vm = qemudFindVMByID(driver, dom->id);
+    virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id);
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          _("no domain with matching id %d"), dom->id);
         return -1;
     }
-    if (!qemudIsActiveVM(vm)) {
+    if (!virDomainIsActive(vm)) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("domain is not running"));
         return -1;
@@ -2048,7 +2083,7 @@ static int qemudDomainResume(virDomainPtr dom) {
 
 static int qemudDomainShutdown(virDomainPtr dom) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByID(driver, dom->id);
+    virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id);
     char* info;
 
     if (!vm) {
@@ -2069,7 +2104,7 @@ static int qemudDomainShutdown(virDomainPtr dom) {
 
 static int qemudDomainDestroy(virDomainPtr dom) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByID(driver, dom->id);
+    virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id);
 
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -2078,8 +2113,9 @@ static int qemudDomainDestroy(virDomainPtr dom) {
     }
 
     qemudShutdownVMDaemon(dom->conn, driver, vm);
-    if (!vm->configFile[0])
-        qemudRemoveInactiveVM(driver, vm);
+    if (!vm->configFile)
+        virDomainRemoveInactive(&driver->domains,
+                                vm);
 
     return 0;
 }
@@ -2087,7 +2123,7 @@ static int qemudDomainDestroy(virDomainPtr dom) {
 
 static char *qemudDomainGetOSType(virDomainPtr dom) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+    virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
     char *type;
 
     if (!vm) {
@@ -2107,7 +2143,7 @@ static char *qemudDomainGetOSType(virDomainPtr dom) {
 /* Returns max memory in kb, 0 if error */
 static unsigned long qemudDomainGetMaxMemory(virDomainPtr dom) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+    virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
 
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -2120,7 +2156,7 @@ static unsigned long qemudDomainGetMaxMemory(virDomainPtr dom) {
 
 static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+    virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
 
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -2140,7 +2176,7 @@ static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
 
 static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+    virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
 
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -2148,7 +2184,7 @@ static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
         return -1;
     }
 
-    if (qemudIsActiveVM(vm)) {
+    if (virDomainIsActive(vm)) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                          "%s", _("cannot set memory of an active domain"));
         return -1;
@@ -2165,9 +2201,9 @@ static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
 }
 
 static int qemudDomainGetInfo(virDomainPtr dom,
-                       virDomainInfoPtr info) {
+                              virDomainInfoPtr info) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+    virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          "%s", _("no domain with matching uuid"));
@@ -2176,7 +2212,7 @@ static int qemudDomainGetInfo(virDomainPtr dom,
 
     info->state = vm->state;
 
-    if (!qemudIsActiveVM(vm)) {
+    if (!virDomainIsActive(vm)) {
         info->cpuTime = 0;
     } else {
         if (qemudGetProcessInfo(&(info->cpuTime), vm->pid) < 0) {
@@ -2288,7 +2324,7 @@ struct qemud_save_header {
 static int qemudDomainSave(virDomainPtr dom,
                            const char *path) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByID(driver, dom->id);
+    virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id);
     char *command, *info;
     int fd;
     char *safe_path;
@@ -2305,7 +2341,7 @@ static int qemudDomainSave(virDomainPtr dom,
         return -1;
     }
 
-    if (!qemudIsActiveVM(vm)) {
+    if (!virDomainIsActive(vm)) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("domain is not running"));
         return -1;
@@ -2322,7 +2358,7 @@ static int qemudDomainSave(virDomainPtr dom,
     }
 
     /* Get XML for the domain */
-    xml = qemudGenerateXML(dom->conn, driver, vm, vm->def, 0);
+    xml = virDomainDefFormat(dom->conn, vm->def, VIR_DOMAIN_XML_SECURE);
     if (!xml) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("failed to get domain xml"));
@@ -2386,8 +2422,9 @@ static int qemudDomainSave(virDomainPtr dom,
 
     /* Shut it down */
     qemudShutdownVMDaemon(dom->conn, driver, vm);
-    if (!vm->configFile[0])
-        qemudRemoveInactiveVM(driver, vm);
+    if (!vm->configFile)
+        virDomainRemoveInactive(&driver->domains,
+                                vm);
 
     return 0;
 }
@@ -2395,7 +2432,7 @@ static int qemudDomainSave(virDomainPtr dom,
 
 static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
     const struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+    virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
     int max;
 
     if (!vm) {
@@ -2404,7 +2441,7 @@ static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
         return -1;
     }
 
-    if (qemudIsActiveVM(vm)) {
+    if (virDomainIsActive(vm)) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s",
                          _("cannot change vcpu count of an active domain"));
         return -1;
@@ -2435,12 +2472,12 @@ qemudDomainPinVcpu(virDomainPtr dom,
                    unsigned char *cpumap,
                    int maplen) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+    virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
     cpu_set_t mask;
     int i, maxcpu;
     virNodeInfo nodeinfo;
 
-    if (!qemudIsActiveVM(vm)) {
+    if (!virDomainIsActive(vm)) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                          "%s",_("cannot pin vcpus on an inactive domain"));
         return -1;
@@ -2488,11 +2525,11 @@ qemudDomainGetVcpus(virDomainPtr dom,
                     unsigned char *cpumaps,
                     int maplen) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+    virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
     virNodeInfo nodeinfo;
     int i, v, maxcpu;
 
-    if (!qemudIsActiveVM(vm)) {
+    if (!virDomainIsActive(vm)) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                          "%s",_("cannot pin vcpus on an inactive domain"));
         return -1;
@@ -2553,7 +2590,7 @@ qemudDomainGetVcpus(virDomainPtr dom,
 
 static int qemudDomainGetMaxVcpus(virDomainPtr dom) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+    virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
     const char *type;
     int ret;
 
@@ -2563,7 +2600,7 @@ static int qemudDomainGetMaxVcpus(virDomainPtr dom) {
         return -1;
     }
 
-    if (!(type = qemudVirtTypeToString(vm->def->virtType))) {
+    if (!(type = virDomainVirtTypeToString(vm->def->virtType))) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                          _("unknown virt type in domain definition '%d'"),
                          vm->def->virtType);
@@ -2581,8 +2618,8 @@ static int qemudDomainGetMaxVcpus(virDomainPtr dom) {
 static int qemudDomainRestore(virConnectPtr conn,
                        const char *path) {
     struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
-    struct qemud_vm_def *def;
-    struct qemud_vm *vm;
+    virDomainDefPtr def;
+    virDomainObjPtr vm;
     int fd;
     int ret;
     char *xml;
@@ -2633,7 +2670,7 @@ static int qemudDomainRestore(virConnectPtr conn,
     }
 
     /* Create a domain from this XML */
-    if (!(def = qemudParseVMDef(conn, driver, xml, NULL))) {
+    if (!(def = virDomainDefParseString(conn, driver->caps, xml))) {
         qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("failed to parse XML"));
         close(fd);
@@ -2643,35 +2680,37 @@ static int qemudDomainRestore(virConnectPtr conn,
     VIR_FREE(xml);
 
     /* Ensure the name and UUID don't already exist in an active VM */
-    vm = qemudFindVMByUUID(driver, def->uuid);
-    if (!vm) vm = qemudFindVMByName(driver, def->name);
-    if (vm && qemudIsActiveVM(vm)) {
+    vm = virDomainFindByUUID(driver->domains, def->uuid);
+    if (!vm)
+        vm = virDomainFindByName(driver->domains, def->name);
+    if (vm && virDomainIsActive(vm)) {
         qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                          _("domain is already active as '%s'"), vm->def->name);
         close(fd);
         return -1;
     }
 
-    if (!(vm = qemudAssignVMDef(conn, driver, def))) {
+    if (!(vm = virDomainAssignDef(conn,
+                                  &driver->domains,
+                                  def))) {
         qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("failed to assign new VM"));
-        qemudFreeVMDef(def);
+        virDomainDefFree(def);
         close(fd);
         return -1;
     }
 
     /* Set the migration source and start it up. */
-    snprintf(vm->migrateFrom, sizeof(vm->migrateFrom), "stdio");
     vm->stdin = fd;
-    ret = qemudStartVMDaemon(conn, driver, vm);
+    ret = qemudStartVMDaemon(conn, driver, vm, "stdio");
     close(fd);
-    vm->migrateFrom[0] = '\0';
     vm->stdin = -1;
     if (ret < 0) {
         qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("failed to start VM"));
-        if (!vm->configFile[0])
-            qemudRemoveInactiveVM(driver, vm);
+        if (!vm->configFile)
+            virDomainRemoveInactive(&driver->domains,
+                                    vm);
         return -1;
     }
 
@@ -2692,26 +2731,29 @@ static int qemudDomainRestore(virConnectPtr conn,
 
 
 static char *qemudDomainDumpXML(virDomainPtr dom,
-                         int flags ATTRIBUTE_UNUSED) {
+                                int flags ATTRIBUTE_UNUSED) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+    virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          "%s", _("no domain with matching uuid"));
         return NULL;
     }
 
-    return qemudGenerateXML(dom->conn, driver, vm, vm->def, 1);
+    return virDomainDefFormat(dom->conn,
+                              (flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ?
+                              vm->newDef : vm->def,
+                              flags);
 }
 
 
 static int qemudListDefinedDomains(virConnectPtr conn,
                             char **const names, int nnames) {
     struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
-    struct qemud_vm *vm = driver->vms;
+    virDomainObjPtr vm = driver->domains;
     int got = 0, i;
     while (vm && got < nnames) {
-        if (!qemudIsActiveVM(vm)) {
+        if (!virDomainIsActive(vm)) {
             if (!(names[got] = strdup(vm->def->name))) {
                 qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
                      "%s", _("failed to allocate space for VM name string"));
@@ -2732,13 +2774,20 @@ static int qemudListDefinedDomains(virConnectPtr conn,
 
 static int qemudNumDefinedDomains(virConnectPtr conn) {
     struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
-    return driver->ninactivevms;
+    int n = 0;
+    virDomainObjPtr dom = driver->domains;
+    while (dom) {
+        if (!virDomainIsActive(dom))
+            n++;
+        dom = dom->next;
+    }
+    return n;
 }
 
 
 static int qemudDomainStart(virDomainPtr dom) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+    virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
 
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -2746,37 +2795,43 @@ static int qemudDomainStart(virDomainPtr dom) {
         return -1;
     }
 
-    return qemudStartVMDaemon(dom->conn, driver, vm);
+    return qemudStartVMDaemon(dom->conn, driver, vm, NULL);
 }
 
 
 static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
     struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
-    struct qemud_vm_def *def;
-    struct qemud_vm *vm;
+    virDomainDefPtr def;
+    virDomainObjPtr vm;
     virDomainPtr dom;
 
-    if (!(def = qemudParseVMDef(conn, driver, xml, NULL)))
+    if (!(def = virDomainDefParseString(conn, driver->caps, xml)))
         return NULL;
 
-    if (!(vm = qemudAssignVMDef(conn, driver, def))) {
-        qemudFreeVMDef(def);
+    if (!(vm = virDomainAssignDef(conn,
+                                  &driver->domains,
+                                  def))) {
+        virDomainDefFree(def);
         return NULL;
     }
 
-    if (qemudSaveVMDef(conn, driver, vm, def) < 0) {
-        qemudRemoveInactiveVM(driver, vm);
+    if (virDomainSaveConfig(conn,
+                            driver->configDir,
+                            driver->autostartDir,
+                            vm) < 0) {
+        virDomainRemoveInactive(&driver->domains,
+                                vm);
         return NULL;
     }
 
     dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
-    if (dom) dom->id = vm->id;
+    if (dom) dom->id = vm->def->id;
     return dom;
 }
 
 static int qemudDomainUndefine(virDomainPtr dom) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+    virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
 
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -2784,35 +2839,29 @@ static int qemudDomainUndefine(virDomainPtr dom) {
         return -1;
     }
 
-    if (qemudIsActiveVM(vm)) {
+    if (virDomainIsActive(vm)) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                          "%s", _("cannot delete active domain"));
         return -1;
     }
 
-    if (qemudDeleteConfig(dom->conn, driver, vm->configFile, vm->def->name) < 0)
+    if (virDomainDeleteConfig(dom->conn, vm) < 0)
         return -1;
 
-    if (unlink(vm->autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR)
-        qemudLog(QEMUD_WARN, _("Failed to delete autostart link '%s': %s"),
-                 vm->autostartLink, strerror(errno));
-
-    vm->configFile[0] = '\0';
-    vm->autostartLink[0] = '\0';
-
-    qemudRemoveInactiveVM(driver, vm);
+    virDomainRemoveInactive(&driver->domains,
+                            vm);
 
     return 0;
 }
 
 static int qemudDomainChangeCDROM(virDomainPtr dom,
-                                  struct qemud_vm *vm,
-                                  struct qemud_vm_disk_def *olddisk,
-                                  struct qemud_vm_disk_def *newdisk) {
+                                  virDomainObjPtr vm,
+                                  virDomainDiskDefPtr olddisk,
+                                  virDomainDiskDefPtr newdisk) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
     char *cmd, *reply, *safe_path;
 
-    if (newdisk->src[0]) {
+    if (newdisk->src) {
         safe_path = qemudEscapeMonitorArg(newdisk->src);
         if (!safe_path) {
             qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
@@ -2852,9 +2901,9 @@ static int qemudDomainChangeCDROM(virDomainPtr dom,
 static int qemudDomainAttachDevice(virDomainPtr dom,
                                    const char *xml) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
-    struct qemud_vm_device_def *dev;
-    struct qemud_vm_disk_def *disk;
+    virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
+    virDomainDeviceDefPtr dev;
+    virDomainDiskDefPtr disk;
 
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -2862,18 +2911,19 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
         return -1;
     }
 
-    if (!qemudIsActiveVM(vm)) {
+    if (!virDomainIsActive(vm)) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                          "%s", _("cannot attach device on inactive domain"));
         return -1;
     }
 
-    dev = qemudParseVMDeviceDef(dom->conn, vm->def, xml);
+    dev = virDomainDeviceDefParse(dom->conn, vm->def, xml);
     if (dev == NULL) {
         return -1;
     }
 
-    if (dev->type != QEMUD_DEVICE_DISK || dev->data.disk.device != QEMUD_DISK_CDROM) {
+    if (dev->type != VIR_DOMAIN_DEVICE_DISK ||
+        dev->data.disk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                          "%s", _("only CDROM disk devices can be attached"));
         VIR_FREE(dev);
@@ -2882,8 +2932,8 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
 
     disk = vm->def->disks;
     while (disk) {
-        if (disk->device == QEMUD_DISK_CDROM &&
-            STREQ(disk->dst, dev->data.disk.dst))
+        if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
+            STREQ(disk->dst, dev->data.disk->dst))
             break;
         disk = disk->next;
     }
@@ -2895,7 +2945,7 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
         return -1;
     }
 
-    if (qemudDomainChangeCDROM(dom, vm, disk, &dev->data.disk) < 0) {
+    if (qemudDomainChangeCDROM(dom, vm, disk, dev->data.disk) < 0) {
         VIR_FREE(dev);
         return -1;
     }
@@ -2907,7 +2957,7 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
 static int qemudDomainGetAutostart(virDomainPtr dom,
                             int *autostart) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+    virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
 
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -2923,7 +2973,7 @@ static int qemudDomainGetAutostart(virDomainPtr dom,
 static int qemudDomainSetAutostart(virDomainPtr dom,
                             int autostart) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+    virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
 
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -2981,14 +3031,14 @@ qemudDomainBlockStats (virDomainPtr dom,
     const char *p, *eol;
     char qemu_dev_name[32];
     size_t len;
-    const struct qemud_vm *vm = qemudFindVMByID(driver, dom->id);
+    const virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id);
 
     if (!vm) {
         qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                           _("no domain with matching id %d"), dom->id);
         return -1;
     }
-    if (!qemudIsActiveVM (vm)) {
+    if (!virDomainIsActive (vm)) {
         qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                           "%s", _("domain is not running"));
         return -1;
@@ -3115,8 +3165,8 @@ qemudDomainInterfaceStats (virDomainPtr dom,
 {
 #ifdef __linux__
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByID (driver, dom->id);
-    struct qemud_vm_net_def *net;
+    virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id);
+    virDomainNetDefPtr net;
 
     if (!vm) {
         qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -3124,7 +3174,7 @@ qemudDomainInterfaceStats (virDomainPtr dom,
         return -1;
     }
 
-    if (!qemudIsActiveVM(vm)) {
+    if (!virDomainIsActive(vm)) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("domain is not running"));
         return -1;
@@ -3138,20 +3188,8 @@ qemudDomainInterfaceStats (virDomainPtr dom,
 
     /* Check the path is one of the domain's network interfaces. */
     for (net = vm->def->nets; net; net = net->next) {
-        switch (net->type) {
-        case QEMUD_NET_NETWORK:
-            if (STREQ (net->dst.network.ifname, path))
-                goto ok;
-            break;
-        case QEMUD_NET_ETHERNET:
-            if (STREQ (net->dst.ethernet.ifname, path))
-                goto ok;
-            break;
-        case QEMUD_NET_BRIDGE:
-            if (STREQ (net->dst.bridge.ifname, path))
-                goto ok;
-            break;
-        }
+        if (STREQ (net->ifname, path))
+            goto ok;
     }
 
     qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
@@ -3175,8 +3213,8 @@ qemudDomainBlockPeek (virDomainPtr dom,
                       unsigned int flags ATTRIBUTE_UNUSED)
 {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByUUID (driver, dom->uuid);
-    int i;
+    virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
+    virDomainDiskDefPtr disk;
     int fd, ret = -1;
 
     if (!vm) {
@@ -3192,8 +3230,9 @@ qemudDomainBlockPeek (virDomainPtr dom,
     }
 
     /* Check the path belongs to this domain. */
-    for (i = 0; i < vm->def->ndisks; ++i) {
-        if (STREQ (vm->def->disks[i].src, path)) goto found;
+    for (disk = vm->def->disks ; disk != NULL ; disk = disk->next) {
+        if (disk->src != NULL &&
+            STREQ (disk->src, path)) goto found;
     }
     qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                       _("invalid path"));
@@ -3232,7 +3271,7 @@ qemudDomainMemoryPeek (virDomainPtr dom,
                        unsigned int flags)
 {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
-    struct qemud_vm *vm = qemudFindVMByID (driver, dom->id);
+    virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id);
     char cmd[256], *info;
     char tmp[] = TEMPDIR "/qemu.mem.XXXXXX";
     int fd = -1, ret = -1;
@@ -3249,7 +3288,7 @@ qemudDomainMemoryPeek (virDomainPtr dom,
         return -1;
     }
 
-    if (!qemudIsActiveVM(vm)) {
+    if (!virDomainIsActive(vm)) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("domain is not running"));
         return -1;
@@ -3405,7 +3444,7 @@ static int qemudListDefinedNetworks(virConnectPtr conn, char **const names, int
 }
 
 static virNetworkPtr qemudNetworkCreate(virConnectPtr conn, const char *xml) {
   struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData;
+ struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData;
     virNetworkDefPtr def;
     virNetworkObjPtr network;
     virNetworkPtr net;
index 9de5d12d8be2d300f81d00989587eeaf8d8bac57..52b798f46a9361c986c87965258e6df355dcd929 100644 (file)
@@ -6,7 +6,7 @@
   <vcpu>1</vcpu>
   <bootloader>/usr/bin/pygrub</bootloader>
   <os>
-    <type>xen</type>
+    <type arch='x86_64' machine='xenner'>xen</type>
   </os>
   <clock offset='utc'/>
   <on_poweroff>destroy</on_poweroff>
index 994433c3199d3c4e10de5c74b92961c54f386761..cbaa1dac08ef00e570b72de162b76c4394a042aa 100644 (file)
@@ -19,6 +19,6 @@
       <target dev='hda' bus='ide'/>
     </disk>
     <input type='mouse' bus='ps2'/>
-    <graphics type='vnc' port='5903' listen='127.0.0.1'/>
+    <graphics type='vnc' port='5903' autoport='no' listen='127.0.0.1'/>
   </devices>
 </domain>
index 44f43b0195b61e444517cf827a570d2052d3e8ec..1e80317c4321085fda04a77030a126426b7ea822 100644 (file)
@@ -6,7 +6,7 @@
   <vcpu>1</vcpu>
   <bootloader>/foo</bootloader>
   <os>
-    <type>xen</type>
+    <type arch='x86_64' machine='xenner'>xen</type>
   </os>
   <clock offset='utc'/>
   <on_poweroff>destroy</on_poweroff>
@@ -19,6 +19,6 @@
       <target dev='hda' bus='ide'/>
     </disk>
     <input type='mouse' bus='xen'/>
-    <graphics type='vnc' port='-1'/>
+    <graphics type='vnc' port='5903' autoport='no' listen='127.0.0.1'/>
   </devices>
 </domain>
index a351f8d17f647538d44b5706199d2a26509c7731..cc85c5320055f65dda3af04a6068b66a0440e0a4 100644 (file)
     <emulator>/usr/bin/qemu</emulator>
     <disk type='block' device='disk'>
       <source dev='/dev/HostVG/QEMUGuest1'/>
-      <target dev='hda'/>
+      <target dev='hda' bus='ide'/>
     </disk>
     <sound model='pcspk'/>
-    <sound model='pcspk'/>
     <sound model='es1370'/>
-    <sound model='pcspk'/>
-    <sound model='sb16'/>
-    <sound model='es1370'/>
-    <sound model='pcspk'/>
     <sound model='sb16'/>
   </devices>
 </domain>
index 336a113f1c7e920f99c83c7e5334b2648c3789ef..5e1871d7100812e62abc3d55da9228a3bc90d39a 100644 (file)
@@ -23,39 +23,33 @@ static struct qemud_driver driver;
 #define MAX_FILE 4096
 
 static int testCompareXMLToArgvFiles(const char *xml, const char *cmd, int extraFlags) {
-    char xmlData[MAX_FILE];
     char argvData[MAX_FILE];
-    char *xmlPtr = &(xmlData[0]);
     char *expectargv = &(argvData[0]);
     char *actualargv = NULL;
     char **argv = NULL;
     char **tmp = NULL;
-    int ret = -1, len;
-    struct qemud_vm_def *vmdef = NULL;
-    struct qemud_vm vm;
-
-    if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0)
-        goto fail;
+    int ret = -1, len, flags;
+    virDomainDefPtr vmdef = NULL;
+    virDomainObj vm;
 
     if (virtTestLoadFile(cmd, &expectargv, MAX_FILE) < 0)
         goto fail;
 
-    if (!(vmdef = qemudParseVMDef(NULL, &driver, xmlData, "test")))
+    if (!(vmdef = virDomainDefParseFile(NULL, driver.caps, xml)))
         goto fail;
 
     memset(&vm, 0, sizeof vm);
     vm.def = vmdef;
+    vm.def->id = -1;
     vm.pid = -1;
-    vm.id = -1;
-    vm.qemuVersion = 0 * 1000 * 100 + (8 * 1000) + 1;
-    vm.qemuCmdFlags = QEMUD_CMD_FLAG_VNC_COLON |
-        QEMUD_CMD_FLAG_NO_REBOOT;
-    vm.qemuCmdFlags |= extraFlags;
-    vm.migrateFrom[0] = '\0';
 
-    vmdef->vncActivePort = vmdef->vncPort;
+    flags = QEMUD_CMD_FLAG_VNC_COLON |
+        QEMUD_CMD_FLAG_NO_REBOOT |
+        extraFlags;
 
-    if (qemudBuildCommandLine(NULL, &driver, &vm, &argv) < 0)
+    if (qemudBuildCommandLine(NULL, &driver,
+                              &vm, flags, &argv,
+                              NULL, NULL, NULL) < 0)
         goto fail;
 
     tmp = argv;
@@ -92,8 +86,7 @@ static int testCompareXMLToArgvFiles(const char *xml, const char *cmd, int extra
         }
         free(argv);
     }
-    if (vmdef)
-        qemudFreeVMDef(vmdef);
+    virDomainDefFree(vmdef);
     return ret;
 }
 
index 53158f2f73d9d1b64aa6a2cfbce692df0445af16..9e380e42622e6f3fabf9a2bdaa532cd644207f79 100644 (file)
@@ -27,25 +27,15 @@ static int testCompareXMLToXMLFiles(const char *xml) {
     char *xmlPtr = &(xmlData[0]);
     char *actual = NULL;
     int ret = -1;
-    struct qemud_vm_def *vmdef = NULL;
-    struct qemud_vm vm;
+    virDomainDefPtr vmdef = NULL;
 
     if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0)
         goto fail;
 
-    if (!(vmdef = qemudParseVMDef(NULL, &driver, xmlData, "test")))
+    if (!(vmdef = virDomainDefParseString(NULL, driver.caps, xmlData)))
         goto fail;
 
-    vm.def = vmdef;
-    vm.pid = -1;
-    vm.id = -1;
-    vm.qemuVersion = 0 * 1000 * 100 + (8 * 1000) + 1;
-    vm.qemuCmdFlags = QEMUD_CMD_FLAG_VNC_COLON |
-        QEMUD_CMD_FLAG_NO_REBOOT;
-
-    vmdef->vncActivePort = vmdef->vncPort;
-
-    if (!(actual = qemudGenerateXML(NULL, &driver, &vm, vmdef, 0)))
+    if (!(actual = virDomainDefFormat(NULL, vmdef, 0)))
         goto fail;
 
     if (STRNEQ(xmlData, actual)) {
@@ -57,8 +47,7 @@ static int testCompareXMLToXMLFiles(const char *xml) {
 
  fail:
     free(actual);
-    if (vmdef)
-        qemudFreeVMDef(vmdef);
+    virDomainDefFree(vmdef);
     return ret;
 }
 
@@ -115,6 +104,7 @@ mymain(int argc, char **argv)
     DO_TEST("misc-no-reboot");
     DO_TEST("net-user");
     DO_TEST("net-virtio");
+    DO_TEST("sound");
 
     DO_TEST("serial-vc");
     DO_TEST("serial-pty");