]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
Added inactive domain management support to the test driver
authorDaniel P. Berrange <berrange@redhat.com>
Thu, 18 Jan 2007 21:08:21 +0000 (21:08 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Thu, 18 Jan 2007 21:08:21 +0000 (21:08 +0000)
ChangeLog
src/test.c
src/test.h

index fde85a12e423e97424f9bc282558a80aa04c1c05..1aef9c9c2d8a39d645c3d87612fa8407add1cbdc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Thu Jan 18 16:05:13 EST 2007 Daniel Berrange <berrange@redhat.com>
+
+       * src/test.h, src/test.c: Implement full inactive domain management
+       support in mock hypervisor to allow testing of apps wanting inactive
+       domains.
+
 Thu Jan 18 13:37:02 EST 2007 Daniel Berrange <berrange@redhat.com>
 
        * src/xend_internal.c: Tweak some of the new inactive domain methods
@@ -14,7 +20,7 @@ Wed Jan 10 11:06:36 CET 2007 Daniel Veillard <veillard@redhat.com>
          fixed or added a number constructs
 
 Tue Jan  9 17:28:18 CET 2007 Daniel Veillard <veillard@redhat.com>
-       
+
        * docs/libvirt.rng: first version of the Relax-NG schemas to validate
          XML instances
 
index c69f1ce54afba60047290cf2dc664b3442fa79cc..eef629ca566b7e1628fbc4a72250d51ac7e1c25b 100644 (file)
@@ -1,9 +1,22 @@
 /*
  * test.c: A "mock" hypervisor for use by application unit tests
  *
- * Copyright (C) 2006 Red Hat, Inc.
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ * Copyright (C) 2006 Daniel P. Berrange
  *
- * See COPYING.LIB for the License of this software
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
  *
  * Daniel Berrange <berrange@redhat.com>
  */
 #include "test.h"
 #include "xml.h"
 
+int testOpen(virConnectPtr conn,
+             const char *name,
+             int flags);
+int testClose  (virConnectPtr conn);
+int testGetVersion(virConnectPtr conn,
+                   unsigned long *hvVer);
+int testNodeGetInfo(virConnectPtr conn,
+                    virNodeInfoPtr info);
+int testNumOfDomains(virConnectPtr conn);
+int testListDomains(virConnectPtr conn,
+                    int *ids,
+                    int maxids);
+char *testGetOSType(virDomainPtr dom);
+virDomainPtr
+testDomainCreateLinux(virConnectPtr conn, const char *xmlDesc,
+                      unsigned int flags ATTRIBUTE_UNUSED);
+virDomainPtr testLookupDomainByID(virConnectPtr conn,
+                                  int id);
+virDomainPtr testLookupDomainByUUID(virConnectPtr conn,
+                                    const unsigned char *uuid);
+virDomainPtr testLookupDomainByName(virConnectPtr conn,
+                                    const char *name);
+int testDestroyDomain(virDomainPtr domain);
+int testResumeDomain(virDomainPtr domain);
+int testPauseDomain(virDomainPtr domain);
+int testShutdownDomain (virDomainPtr domain);
+int testRebootDomain (virDomainPtr domain,
+                      virDomainRestart action);
+int testGetDomainInfo(virDomainPtr domain,
+                      virDomainInfoPtr info);
+unsigned long testGetMaxMemory(virDomainPtr domain);
+int testSetMaxMemory(virDomainPtr domain,
+                     unsigned long memory);
+int testSetMemory(virDomainPtr domain,
+                  unsigned long memory);
+int testSetVcpus(virDomainPtr domain,
+                 unsigned int nrCpus);
+char * testDomainDumpXML(virDomainPtr domain, int flags);
+
+int testNumOfDefinedDomains(virConnectPtr conn);
+int testListDefinedDomains(virConnectPtr conn,
+                           const char **names,
+                           int maxnames);
+
+virDomainPtr testDomainDefineXML(virConnectPtr conn,
+                                 const char *xml);
+
+int testDomainCreate(virDomainPtr dom);
+
+int testDomainUndefine(virDomainPtr dom);
+
 static virDriver testDriver = {
-  VIR_DRV_TEST,
-  "Test",
-  LIBVIR_VERSION_NUMBER,
-  NULL, /* init */
-  testOpen, /* open */
-  testClose, /* close */
-  NULL, /* type */
-  testGetVersion, /* version */
-  testNodeGetInfo, /* nodeGetInfo */
-  testListDomains, /* listDomains */
-  testNumOfDomains, /* numOfDomains */
-  testDomainCreateLinux, /* domainCreateLinux */
-  testLookupDomainByID, /* domainLookupByID */
-  testLookupDomainByUUID, /* domainLookupByUUID */
-  testLookupDomainByName, /* domainLookupByName */
-  testPauseDomain, /* domainSuspend */
-  testResumeDomain, /* domainResume */
-  testShutdownDomain, /* domainShutdown */
-  testRebootDomain, /* domainReboot */
-  testDestroyDomain, /* domainDestroy */
-  NULL, /* domainFree */
-  NULL, /* domainGetName */
-  NULL, /* domainGetID */
-  NULL, /* domainGetUUID */
-  testGetOSType, /* domainGetOSType */
-  testGetMaxMemory, /* domainGetMaxMemory */
-  testSetMaxMemory, /* domainSetMaxMemory */
-  testSetMemory, /* domainSetMemory */
-  testGetDomainInfo, /* domainGetInfo */
-  NULL, /* domainSave */
-  NULL, /* domainRestore */
-  NULL, /* domainCoreDump */
-  testSetVcpus, /* domainSetVcpus */
-  NULL, /* domainPinVcpu */
-  NULL, /* domainGetVcpus */
-  testDomainDumpXML, /* domainDumpXML */
-  NULL, /* listDefinedDomains */
-  NULL, /* numOfDefinedDomains */
-  NULL, /* domainCreate */
-  NULL, /* domainDefineXML */
-  NULL, /* domainUndefine */
-  NULL, /* domainAttachDevice */
-  NULL, /* domainDetachDevice */
+    VIR_DRV_TEST,
+    "Test",
+    LIBVIR_VERSION_NUMBER,
+    NULL, /* init */
+    testOpen, /* open */
+    testClose, /* close */
+    NULL, /* type */
+    testGetVersion, /* version */
+    testNodeGetInfo, /* nodeGetInfo */
+    testListDomains, /* listDomains */
+    testNumOfDomains, /* numOfDomains */
+    testDomainCreateLinux, /* domainCreateLinux */
+    testLookupDomainByID, /* domainLookupByID */
+    testLookupDomainByUUID, /* domainLookupByUUID */
+    testLookupDomainByName, /* domainLookupByName */
+    testPauseDomain, /* domainSuspend */
+    testResumeDomain, /* domainResume */
+    testShutdownDomain, /* domainShutdown */
+    testRebootDomain, /* domainReboot */
+    testDestroyDomain, /* domainDestroy */
+    NULL, /* domainFree */
+    NULL, /* domainGetName */
+    NULL, /* domainGetID */
+    NULL, /* domainGetUUID */
+    testGetOSType, /* domainGetOSType */
+    testGetMaxMemory, /* domainGetMaxMemory */
+    testSetMaxMemory, /* domainSetMaxMemory */
+    testSetMemory, /* domainSetMemory */
+    testGetDomainInfo, /* domainGetInfo */
+    NULL, /* domainSave */
+    NULL, /* domainRestore */
+    NULL, /* domainCoreDump */
+    testSetVcpus, /* domainSetVcpus */
+    NULL, /* domainPinVcpu */
+    NULL, /* domainGetVcpus */
+    testDomainDumpXML, /* domainDumpXML */
+    testListDefinedDomains, /* listDefinedDomains */
+    testNumOfDefinedDomains, /* numOfDefinedDomains */
+    testDomainCreate, /* domainCreate */
+    testDomainDefineXML, /* domainDefineXML */
+    testDomainUndefine, /* domainUndefine */
+    NULL, /* domainAttachDevice */
+    NULL, /* domainDetachDevice */
 };
 
-/* Amount of time it takes to shutdown */
-#define SHUTDOWN_DURATION 15
-
 typedef struct _testDev {
-  char name[20];
-  virDeviceMode mode;
+    char name[20];
+    virDeviceMode mode;
 } testDev;
 
 #define MAX_DEVICES 10
 
 typedef struct _testDom {
-  int active;
-  char name[20];
-  unsigned char uuid[16];
-  virDomainKernel kernel;
-  virDomainInfo info;
-  time_t shutdownStartedAt;
-  virDomainRestart onRestart; /* What to do at end of current shutdown procedure */
-  virDomainRestart onReboot;
-  virDomainRestart onPoweroff;
-  virDomainRestart onCrash;
-  int numDevices;
-  testDev devices[MAX_DEVICES];
+    int active;
+    int handle;
+    char name[20];
+    unsigned char uuid[16];
+    virDomainKernel kernel;
+    virDomainInfo info;
+    unsigned int maxVCPUs;
+    virDomainRestart onRestart; /* What to do at end of current shutdown procedure */
+    virDomainRestart onReboot;
+    virDomainRestart onPoweroff;
+    virDomainRestart onCrash;
+    int numDevices;
+    testDev devices[MAX_DEVICES];
 } testDom;
 
 #define MAX_DOMAINS 20
 
 typedef struct _testCon {
-  int active;
-  virNodeInfo nodeInfo;
-  int numDomains;
-  testDom domains[MAX_DOMAINS];
+    int active;
+    virNodeInfo nodeInfo;
+    int numDomains;
+    testDom domains[MAX_DOMAINS];
 } testCon;
 
 #define MAX_CONNECTIONS 5
 
 typedef struct _testNode {
-  int numConnections;
-  testCon connections[MAX_CONNECTIONS];
+    int numConnections;
+    testCon connections[MAX_CONNECTIONS];
 } testNode;
 
 /* XXX, how about we stuff this in a SHM
@@ -115,60 +177,61 @@ typedef struct _testNode {
    Would need a pthread process shared mutex
    too probably */
 static testNode *node = NULL;
+static int nextDomID = 1;
 
 static const virNodeInfo defaultNodeInfo = {
-  "i686",
-  1024*1024*3, /* 3 GB */
-  16,
-  1400,
-  2,
-  2,
-  2,
-  2,
+    "i686",
+    1024*1024*3, /* 3 GB */
+    16,
+    1400,
+    2,
+    2,
+    2,
+    2,
 };
 
 static void
 testError(virConnectPtr con,
-         virDomainPtr dom,
-         virErrorNumber error,
-         const char *info)
+          virDomainPtr dom,
+          virErrorNumber error,
+          const char *info)
 {
-  const char *errmsg;
+    const char *errmsg;
 
-  if (error == VIR_ERR_OK)
-    return;
+    if (error == VIR_ERR_OK)
+        return;
 
-  errmsg = __virErrorMsg(error, info);
-  __virRaiseError(con, dom, VIR_FROM_XEN, error, VIR_ERR_ERROR,
-                 errmsg, info, NULL, 0, 0, errmsg, info, 0);
+    errmsg = __virErrorMsg(error, info);
+    __virRaiseError(con, dom, VIR_FROM_XEN, error, VIR_ERR_ERROR,
+                    errmsg, info, NULL, 0, 0, errmsg, info, 0);
 }
 
 static int testRestartStringToFlag(const char *str) {
-  if (!strcmp(str, "restart")) {
-    return VIR_DOMAIN_RESTART;
-  } else if (!strcmp(str, "destroy")) {
-    return VIR_DOMAIN_DESTROY;
-  } else if (!strcmp(str, "preserve")) {
-    return VIR_DOMAIN_PRESERVE;
-  } else if (!strcmp(str, "rename-restart")) {
-    return VIR_DOMAIN_RENAME_RESTART;
-  } else {
-    return 0;
-  }
+    if (!strcmp(str, "restart")) {
+        return VIR_DOMAIN_RESTART;
+    } else if (!strcmp(str, "destroy")) {
+        return VIR_DOMAIN_DESTROY;
+    } else if (!strcmp(str, "preserve")) {
+        return VIR_DOMAIN_PRESERVE;
+    } else if (!strcmp(str, "rename-restart")) {
+        return VIR_DOMAIN_RENAME_RESTART;
+    } else {
+        return (0);
+    }
 }
 
 static const char *testRestartFlagToString(int flag) {
-  switch (flag) {
-  case VIR_DOMAIN_RESTART:
-    return "restart";
-  case VIR_DOMAIN_DESTROY:
-    return "destroy";
-  case VIR_DOMAIN_PRESERVE:
-    return "preserve";
-  case VIR_DOMAIN_RENAME_RESTART:
-    return "rename-restart";
-  }
-  return NULL;
+    switch (flag) {
+    case VIR_DOMAIN_RESTART:
+        return "restart";
+    case VIR_DOMAIN_DESTROY:
+        return "destroy";
+    case VIR_DOMAIN_PRESERVE:
+        return "preserve";
+    case VIR_DOMAIN_RENAME_RESTART:
+        return "rename-restart";
+    }
+    return (NULL);
 }
 
 /**
@@ -178,700 +241,784 @@ static const char *testRestartFlagToString(int flag) {
  */
 void testRegister(void)
 {
-  virRegisterDriver(&testDriver);
+    virRegisterDriver(&testDriver);
 }
 
 static int testLoadDomain(virConnectPtr conn,
-                         int domid,
-                         xmlDocPtr xml) {
-  xmlNodePtr root = NULL;
-  xmlXPathContextPtr ctxt = NULL;
-  xmlXPathObjectPtr obj = NULL;
-  char *name = NULL;
-  unsigned char rawuuid[16];
-  char *dst_uuid;
-  testCon *con;
-  struct timeval tv;
-  unsigned long memory;
-  int nrVirtCpu;
-  char *conv;
-  virDomainRestart onReboot = VIR_DOMAIN_RESTART;
-  virDomainRestart onPoweroff = VIR_DOMAIN_DESTROY;
-  virDomainRestart onCrash = VIR_DOMAIN_RENAME_RESTART;
-
-  if (gettimeofday(&tv, NULL) < 0) {
-    testError(conn, NULL, VIR_ERR_INTERNAL_ERROR, _("getting time of day"));
-    return -1;
-  }
-
-  root = xmlDocGetRootElement(xml);
-  if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "domain"))) {
-    testError(conn, NULL, VIR_ERR_XML_ERROR, _("domain"));
-    goto error;
-  }
-
-  ctxt = xmlXPathNewContext(xml);
-  if (ctxt == NULL) {
-    testError(conn, NULL, VIR_ERR_INTERNAL_ERROR, _("creating xpath context"));
-    goto error;
-  }
-
-  obj = xmlXPathEval(BAD_CAST "string(/domain/name[1])", ctxt);
-  if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-      (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-    testError(conn, NULL, VIR_ERR_INTERNAL_ERROR, _("domain name"));
-    goto error;
-  }
-  name = strdup((const char *)obj->stringval);
-  xmlXPathFreeObject(obj);
-
-  obj = xmlXPathEval(BAD_CAST "string(/domain/uuid[1])", ctxt);
-  if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-      (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-    testError(conn, NULL, VIR_ERR_XML_ERROR, _("domain uuid"));
-    goto error;
-  }
-  dst_uuid = (char *) &rawuuid[0];
-  if (!(virParseUUID((char **)&dst_uuid, (const char *)obj->stringval))) {
-    testError(conn, NULL, VIR_ERR_XML_ERROR, _("domain uuid"));
-    goto error;
-  }
-  xmlXPathFreeObject(obj);
-
-  obj = xmlXPathEval(BAD_CAST "string(/domain/memory[1])", ctxt);
-  if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-      (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-    testError(conn, NULL, VIR_ERR_XML_ERROR, _("domain memory"));
-    goto error;
-  }
-  memory = strtoll((const char*)obj->stringval, &conv, 10);
-  if (conv == (const char*)obj->stringval) {
-    testError(conn, NULL, VIR_ERR_XML_ERROR, _("domain memory"));
-    goto error;
-  }
-  xmlXPathFreeObject(obj);
-
-  obj = xmlXPathEval(BAD_CAST "string(/domain/vcpu[1])", ctxt);
-  if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-      (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-    nrVirtCpu = 1;
-  } else {
-    nrVirtCpu = strtoll((const char*)obj->stringval, &conv, 10);
-    if (conv == (const char*)obj->stringval) {
-      testError(conn, NULL, VIR_ERR_XML_ERROR, _("domain vcpus"));
-      goto error;
+                          int domid,
+                          xmlDocPtr xml) {
+    xmlNodePtr root = NULL;
+    xmlXPathContextPtr ctxt = NULL;
+    xmlXPathObjectPtr obj = NULL;
+    char *name = NULL;
+    unsigned char rawuuid[16];
+    char *dst_uuid;
+    testCon *con;
+    struct timeval tv;
+    unsigned long memory = 0;
+    unsigned long maxMem = 0;
+    int nrVirtCpu;
+    char *conv;
+    int handle = -1, i;
+    virDomainRestart onReboot = VIR_DOMAIN_RESTART;
+    virDomainRestart onPoweroff = VIR_DOMAIN_DESTROY;
+    virDomainRestart onCrash = VIR_DOMAIN_RENAME_RESTART;
+
+    if (gettimeofday(&tv, NULL) < 0) {
+        testError(conn, NULL, VIR_ERR_INTERNAL_ERROR, _("getting time of day"));
+        return (-1);
     }
-  }
-  if (obj)
-    xmlXPathFreeObject(obj);
 
-  obj = xmlXPathEval(BAD_CAST "string(/domain/on_reboot[1])", ctxt);
-  if ((obj != NULL) && (obj->type == XPATH_STRING) &&
-      (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
-    if (!(onReboot = testRestartStringToFlag((const char *)obj->stringval))) {
-      testError(conn, NULL, VIR_ERR_XML_ERROR, _("domain reboot behaviour"));
-      goto error;
+    root = xmlDocGetRootElement(xml);
+    if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "domain"))) {
+        testError(conn, NULL, VIR_ERR_XML_ERROR, _("domain"));
+        goto error;
     }
-  }
-  if (obj)
+
+    ctxt = xmlXPathNewContext(xml);
+    if (ctxt == NULL) {
+        testError(conn, NULL, VIR_ERR_INTERNAL_ERROR, _("creating xpath context"));
+        goto error;
+    }
+
+    obj = xmlXPathEval(BAD_CAST "string(/domain/name[1])", ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
+        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
+        testError(conn, NULL, VIR_ERR_INTERNAL_ERROR, _("domain name"));
+        goto error;
+    }
+    name = strdup((const char *)obj->stringval);
     xmlXPathFreeObject(obj);
 
-  obj = xmlXPathEval(BAD_CAST "string(/domain/on_poweroff[1])", ctxt);
-  if ((obj != NULL) && (obj->type == XPATH_STRING) &&
-      (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
-    if (!(onReboot = testRestartStringToFlag((const char *)obj->stringval))) {
-      testError(conn, NULL, VIR_ERR_XML_ERROR, _("domain poweroff behaviour"));
-      goto error;
+    obj = xmlXPathEval(BAD_CAST "string(/domain/uuid[1])", ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
+        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
+        testError(conn, NULL, VIR_ERR_XML_ERROR, _("domain uuid"));
+        goto error;
+    }
+    dst_uuid = (char *) &rawuuid[0];
+    if (!(virParseUUID((char **)&dst_uuid, (const char *)obj->stringval))) {
+        testError(conn, NULL, VIR_ERR_XML_ERROR, _("domain uuid"));
+        goto error;
     }
-  }
-  if (obj)
     xmlXPathFreeObject(obj);
 
-  obj = xmlXPathEval(BAD_CAST "string(/domain/on_crash[1])", ctxt);
-  if ((obj != NULL) && (obj->type == XPATH_STRING) &&
-      (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
-    if (!(onReboot = testRestartStringToFlag((const char *)obj->stringval))) {
-      testError(conn, NULL, VIR_ERR_XML_ERROR, _("domain crash behaviour"));
-      goto error;
+    obj = xmlXPathEval(BAD_CAST "string(/domain/memory[1])", ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
+        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
+        testError(conn, NULL, VIR_ERR_XML_ERROR, _("domain memory"));
+        goto error;
+    }
+    maxMem = strtoll((const char*)obj->stringval, &conv, 10);
+    if (conv == (const char*)obj->stringval) {
+        testError(conn, NULL, VIR_ERR_XML_ERROR, _("domain memory"));
+        goto error;
     }
-  }
-  if (obj)
     xmlXPathFreeObject(obj);
 
-  con = &node->connections[conn->handle];
 
-  con->domains[domid].active = 1;
-  strncpy(con->domains[domid].name, name, sizeof(con->domains[domid].name));
-  free(name);
-  name = NULL;
+    obj = xmlXPathEval(BAD_CAST "string(/domain/currentMemory[1])", ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
+        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
+        memory = maxMem;
+    } else {
+        memory = strtoll((const char*)obj->stringval, &conv, 10);
+        if (conv == (const char*)obj->stringval) {
+            testError(conn, NULL, VIR_ERR_XML_ERROR, _("domain current memory"));
+            goto error;
+        }
+    }
+    if (obj)
+        xmlXPathFreeObject(obj);
+
+
 
-  memmove(con->domains[domid].uuid, rawuuid, 16);
-  con->domains[domid].info.maxMem = memory;
-  con->domains[domid].info.memory = memory;
-  con->domains[domid].info.state = VIR_DOMAIN_RUNNING;
-  con->domains[domid].info.nrVirtCpu = nrVirtCpu;
-  con->domains[domid].info.cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
 
-  con->domains[domid].onReboot = onReboot;
-  con->domains[domid].onPoweroff = onPoweroff;
-  con->domains[domid].onCrash = onCrash;
+    obj = xmlXPathEval(BAD_CAST "string(/domain/vcpu[1])", ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
+        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
+        nrVirtCpu = 1;
+    } else {
+        nrVirtCpu = strtoll((const char*)obj->stringval, &conv, 10);
+        if (conv == (const char*)obj->stringval) {
+            testError(conn, NULL, VIR_ERR_XML_ERROR, _("domain vcpus"));
+            goto error;
+        }
+    }
+    if (obj)
+        xmlXPathFreeObject(obj);
+
+    obj = xmlXPathEval(BAD_CAST "string(/domain/on_reboot[1])", ctxt);
+    if ((obj != NULL) && (obj->type == XPATH_STRING) &&
+        (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
+        if (!(onReboot = testRestartStringToFlag((const char *)obj->stringval))) {
+            testError(conn, NULL, VIR_ERR_XML_ERROR, _("domain reboot behaviour"));
+            goto error;
+        }
+    }
+    if (obj)
+        xmlXPathFreeObject(obj);
+
+    obj = xmlXPathEval(BAD_CAST "string(/domain/on_poweroff[1])", ctxt);
+    if ((obj != NULL) && (obj->type == XPATH_STRING) &&
+        (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
+        if (!(onReboot = testRestartStringToFlag((const char *)obj->stringval))) {
+            testError(conn, NULL, VIR_ERR_XML_ERROR, _("domain poweroff behaviour"));
+            goto error;
+        }
+    }
+    if (obj)
+        xmlXPathFreeObject(obj);
+
+    obj = xmlXPathEval(BAD_CAST "string(/domain/on_crash[1])", ctxt);
+    if ((obj != NULL) && (obj->type == XPATH_STRING) &&
+        (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
+        if (!(onReboot = testRestartStringToFlag((const char *)obj->stringval))) {
+            testError(conn, NULL, VIR_ERR_XML_ERROR, _("domain crash behaviour"));
+            goto error;
+        }
+    }
+    if (obj)
+        xmlXPathFreeObject(obj);
 
-  return 0;
+    con = &node->connections[conn->handle];
 
- error:
-  if (obj)
-    xmlXPathFreeObject(obj);
-  if (name)
+    for (i = 0 ; i < MAX_DOMAINS ; i++) {
+        if (!con->domains[i].active) {
+            handle = i;
+            break;
+        }
+    }
+    if (handle < 0)
+        return (-1);
+
+    con->domains[handle].active = 1;
+    con->domains[handle].handle = domid;
+    strncpy(con->domains[handle].name, name, sizeof(con->domains[handle].name));
     free(name);
-  return -1;
+    name = NULL;
+
+    if (memory > maxMem)
+        memory = maxMem;
+
+    memmove(con->domains[handle].uuid, rawuuid, 16);
+    con->domains[handle].info.maxMem = maxMem;
+    con->domains[handle].info.memory = memory;
+    con->domains[handle].info.state = domid < 0 ? VIR_DOMAIN_SHUTOFF : VIR_DOMAIN_RUNNING;
+    con->domains[handle].info.nrVirtCpu = nrVirtCpu;
+    con->domains[handle].info.cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
+    con->domains[handle].maxVCPUs = nrVirtCpu;
+
+    con->domains[handle].onReboot = onReboot;
+    con->domains[handle].onPoweroff = onPoweroff;
+    con->domains[handle].onCrash = onCrash;
+
+    return (0);
+
+ error:
+    if (obj)
+        xmlXPathFreeObject(obj);
+    if (name)
+        free(name);
+    return (-1);
 }
 
 static int testLoadDomainFromDoc(virConnectPtr conn,
-                                int domid,
-                                const char *doc) {
-  int ret;
-  xmlDocPtr xml;
-  if (!(xml = xmlReadDoc(BAD_CAST doc, "domain.xml", NULL,
-                        XML_PARSE_NOENT | XML_PARSE_NONET |
-                        XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
-    testError(NULL, NULL, VIR_ERR_XML_ERROR, _("domain"));
-    return -1;
-  }
-
-  ret = testLoadDomain(conn, domid, xml);
-
-  xmlFreeDoc(xml);
-
-  return ret;
+                                 int domid,
+                                 const char *doc) {
+    int ret;
+    xmlDocPtr xml;
+    if (!(xml = xmlReadDoc(BAD_CAST doc, "domain.xml", NULL,
+                           XML_PARSE_NOENT | XML_PARSE_NONET |
+                           XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
+        testError(NULL, NULL, VIR_ERR_XML_ERROR, _("domain"));
+        return (-1);
+    }
+
+    ret = testLoadDomain(conn, domid, xml);
+
+    xmlFreeDoc(xml);
+
+    return (ret);
 }
 
 static int testLoadDomainFromFile(virConnectPtr conn,
-                                 int domid,
-                                 const char *file) {
-  int ret, fd;
-  xmlDocPtr xml;
-
-  if ((fd = open(file, O_RDONLY)) < 0) {
-    testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("load domain definition file"));
-    return -1;
-  }
-
-  if (!(xml = xmlReadFd(fd, file, NULL,
-                       XML_PARSE_NOENT | XML_PARSE_NONET |
-                       XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
-    testError(NULL, NULL, VIR_ERR_XML_ERROR, _("domain"));
+                                  int domid,
+                                  const char *file) {
+    int ret, fd;
+    xmlDocPtr xml;
+
+    if ((fd = open(file, O_RDONLY)) < 0) {
+        testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("load domain definition file"));
+        return (-1);
+    }
+
+    if (!(xml = xmlReadFd(fd, file, NULL,
+                          XML_PARSE_NOENT | XML_PARSE_NONET |
+                          XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
+        testError(NULL, NULL, VIR_ERR_XML_ERROR, _("domain"));
+        close(fd);
+        return (-1);
+    }
     close(fd);
-    return -1;
-  }
-  close(fd);
 
-  ret = testLoadDomain(conn, domid, xml);
+    ret = testLoadDomain(conn, domid, xml);
 
-  xmlFreeDoc(xml);
+    xmlFreeDoc(xml);
 
-  return ret;
+    return (ret);
 }
 
 
 static int testOpenDefault(virConnectPtr conn,
-                          int connid) {
-  int u;
-  struct timeval tv;
-
-  if (gettimeofday(&tv, NULL) < 0) {
-    testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("getting time of day"));
-    return -1;
-  }
-
-  conn->handle = connid;
-  node->connections[connid].active = 1;
-  memmove(&node->connections[connid].nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));
-
-  node->connections[connid].numDomains = 1;
-  node->connections[connid].domains[0].active = 1;
-  strcpy(node->connections[connid].domains[0].name, "Domain-0");
-  for (u = 0 ; u < 16 ; u++) {
-    node->connections[connid].domains[0].uuid[u] = (u * 75)%255;
-  }
-  node->connections[connid].domains[0].info.maxMem = 8192 * 1024;
-  node->connections[connid].domains[0].info.memory = 2048 * 1024;
-  node->connections[connid].domains[0].info.state = VIR_DOMAIN_RUNNING;
-  node->connections[connid].domains[0].info.nrVirtCpu = 2;
-  node->connections[connid].domains[0].info.cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
-  return 0;
+                           int connid) {
+    int u;
+    struct timeval tv;
+
+    if (gettimeofday(&tv, NULL) < 0) {
+        testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("getting time of day"));
+        return (-1);
+    }
+
+    conn->handle = connid;
+    node->connections[connid].active = 1;
+    memmove(&node->connections[connid].nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));
+
+    node->connections[connid].numDomains = 1;
+    node->connections[connid].domains[0].active = 1;
+    node->connections[connid].domains[0].handle = nextDomID++;
+    node->connections[connid].domains[0].onReboot = VIR_DOMAIN_RESTART;
+    node->connections[connid].domains[0].onCrash = VIR_DOMAIN_RESTART;
+    node->connections[connid].domains[0].onPoweroff = VIR_DOMAIN_DESTROY;
+    strcpy(node->connections[connid].domains[0].name, "test");
+    for (u = 0 ; u < 16 ; u++) {
+        node->connections[connid].domains[0].uuid[u] = (u * 75)%255;
+    }
+    node->connections[connid].domains[0].info.maxMem = 8192 * 1024;
+    node->connections[connid].domains[0].info.memory = 2048 * 1024;
+    node->connections[connid].domains[0].info.state = VIR_DOMAIN_RUNNING;
+    node->connections[connid].domains[0].info.nrVirtCpu = 2;
+    node->connections[connid].domains[0].info.cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
+    return (0);
 }
 
 
 static char *testBuildFilename(const char *relativeTo,
-                              const char *filename) {
-  char *offset;
-  int baseLen;
-  if (!filename || filename[0] == '\0')
-    return NULL;
-  if (filename[0] == '/')
-    return strdup(filename);
-
-  offset = rindex(relativeTo, '/');
-  if ((baseLen = (offset-relativeTo+1))) {
-    char *absFile = malloc(baseLen + strlen(filename) + 1);
-    strncpy(absFile, relativeTo, baseLen);
-    absFile[baseLen] = '\0';
-    strcat(absFile, filename);
-    return absFile;
-  } else {
-    return strdup(filename);
-  }
+                               const char *filename) {
+    char *offset;
+    int baseLen;
+    if (!filename || filename[0] == '\0')
+        return (NULL);
+    if (filename[0] == '/')
+        return strdup(filename);
+
+    offset = rindex(relativeTo, '/');
+    if ((baseLen = (offset-relativeTo+1))) {
+        char *absFile = malloc(baseLen + strlen(filename) + 1);
+        strncpy(absFile, relativeTo, baseLen);
+        absFile[baseLen] = '\0';
+        strcat(absFile, filename);
+        return absFile;
+    } else {
+        return strdup(filename);
+    }
 }
 
 static int testOpenFromFile(virConnectPtr conn,
-                           int connid,
-                           const char *file) {
-  int fd, i;
-  xmlDocPtr xml;
-  xmlNodePtr root = NULL;
-  xmlXPathContextPtr ctxt = NULL;
-  xmlXPathObjectPtr obj = NULL;
-  virNodeInfoPtr nodeInfo;
-
-  if ((fd = open(file, O_RDONLY)) < 0) {
-    testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("loading host definition file"));
-    return -1;
-  }
-
-  if (!(xml = xmlReadFd(fd, file, NULL,
-                       XML_PARSE_NOENT | XML_PARSE_NONET |
-                       XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
-    testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("host"));
-    goto error;
-  }
-  close(fd);
-  fd = -1;
-
-  root = xmlDocGetRootElement(xml);
-  if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "node"))) {
-    testError(NULL, NULL, VIR_ERR_XML_ERROR, _("node"));
-    goto error;
-  }
-
-  ctxt = xmlXPathNewContext(xml);
-  if (ctxt == NULL) {
-    testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("creating xpath context"));
-    goto error;
-  }
-
-  conn->handle = connid;
-  node->connections[connid].active = 1;
-  node->connections[connid].numDomains = 0;
-  memmove(&node->connections[connid].nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));
-
-  nodeInfo = &node->connections[connid].nodeInfo;
-  obj = xmlXPathEval(BAD_CAST "string(/node/cpu/nodes[1])", ctxt);
-  if ((obj != NULL) && (obj->type == XPATH_STRING) &&
-      (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
-    char *conv = NULL;
-    nodeInfo->nodes = strtol((const char*)obj->stringval, &conv, 10);
-    if (conv == (const char*)obj->stringval) {
-      testError(conn, NULL, VIR_ERR_XML_ERROR, _("node cpu numa nodes"));
-      goto error;
+                            int connid,
+                            const char *file) {
+    int fd, i;
+    xmlDocPtr xml;
+    xmlNodePtr root = NULL;
+    xmlXPathContextPtr ctxt = NULL;
+    xmlXPathObjectPtr obj = NULL;
+    virNodeInfoPtr nodeInfo;
+
+    if ((fd = open(file, O_RDONLY)) < 0) {
+        testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("loading host definition file"));
+        return (-1);
     }
-    xmlXPathFreeObject(obj);
-  }
 
-  obj = xmlXPathEval(BAD_CAST "string(/node/cpu/sockets[1])", ctxt);
-  if ((obj != NULL) && (obj->type == XPATH_STRING) &&
-      (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
-    char *conv = NULL;
-    nodeInfo->sockets = strtol((const char*)obj->stringval, &conv, 10);
-    if (conv == (const char*)obj->stringval) {
-      testError(conn, NULL, VIR_ERR_XML_ERROR, _("node cpu sockets"));
-      goto error;
+    if (!(xml = xmlReadFd(fd, file, NULL,
+                          XML_PARSE_NOENT | XML_PARSE_NONET |
+                          XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
+        testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("host"));
+        goto error;
     }
-    xmlXPathFreeObject(obj);
-  }
+    close(fd);
+    fd = -1;
 
-  obj = xmlXPathEval(BAD_CAST "string(/node/cpu/cores[1])", ctxt);
-  if ((obj != NULL) && (obj->type == XPATH_STRING) &&
-      (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
-    char *conv = NULL;
-    nodeInfo->cores = strtol((const char*)obj->stringval, &conv, 10);
-    if (conv == (const char*)obj->stringval) {
-      testError(conn, NULL, VIR_ERR_XML_ERROR, _("node cpu cores"));
-      goto error;
+    root = xmlDocGetRootElement(xml);
+    if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "node"))) {
+        testError(NULL, NULL, VIR_ERR_XML_ERROR, _("node"));
+        goto error;
     }
-    xmlXPathFreeObject(obj);
-  }
 
-  obj = xmlXPathEval(BAD_CAST "string(/node/cpu/threads[1])", ctxt);
-  if ((obj != NULL) && (obj->type == XPATH_STRING) &&
-      (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
-    char *conv = NULL;
-    nodeInfo->threads = strtol((const char*)obj->stringval, &conv, 10);
-    if (conv == (const char*)obj->stringval) {
-      testError(conn, NULL, VIR_ERR_XML_ERROR, _("node cpu threads"));
-      goto error;
+    ctxt = xmlXPathNewContext(xml);
+    if (ctxt == NULL) {
+        testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("creating xpath context"));
+        goto error;
     }
-    xmlXPathFreeObject(obj);
-  }
-  nodeInfo->cpus = nodeInfo->cores * nodeInfo->threads * nodeInfo->sockets * nodeInfo->nodes;
-  obj = xmlXPathEval(BAD_CAST "string(/node/cpu/active[1])", ctxt);
-  if ((obj != NULL) && (obj->type == XPATH_STRING) &&
-      (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
-    char *conv = NULL;
-    unsigned int active = strtol((const char*)obj->stringval, &conv, 10);    
-    if (conv == (const char*)obj->stringval) {
-      testError(conn, NULL, VIR_ERR_XML_ERROR, _("node active cpu"));
-      goto error;
+
+    conn->handle = connid;
+    node->connections[connid].active = 1;
+    node->connections[connid].numDomains = 0;
+    memmove(&node->connections[connid].nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));
+
+    nodeInfo = &node->connections[connid].nodeInfo;
+    obj = xmlXPathEval(BAD_CAST "string(/node/cpu/nodes[1])", ctxt);
+    if ((obj != NULL) && (obj->type == XPATH_STRING) &&
+        (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
+        char *conv = NULL;
+        nodeInfo->nodes = strtol((const char*)obj->stringval, &conv, 10);
+        if (conv == (const char*)obj->stringval) {
+            testError(conn, NULL, VIR_ERR_XML_ERROR, _("node cpu numa nodes"));
+            goto error;
+        }
+        xmlXPathFreeObject(obj);
     }
-    if (active < nodeInfo->cpus) {
-      nodeInfo->cpus = active;
+
+    obj = xmlXPathEval(BAD_CAST "string(/node/cpu/sockets[1])", ctxt);
+    if ((obj != NULL) && (obj->type == XPATH_STRING) &&
+        (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
+        char *conv = NULL;
+        nodeInfo->sockets = strtol((const char*)obj->stringval, &conv, 10);
+        if (conv == (const char*)obj->stringval) {
+            testError(conn, NULL, VIR_ERR_XML_ERROR, _("node cpu sockets"));
+            goto error;
+        }
+        xmlXPathFreeObject(obj);
     }
-    xmlXPathFreeObject(obj);
-  }
-  obj = xmlXPathEval(BAD_CAST "string(/node/cpu/mhz[1])", ctxt);
-  if ((obj != NULL) && (obj->type == XPATH_STRING) &&
-      (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
-    char *conv = NULL;
-    nodeInfo->mhz = strtol((const char*)obj->stringval, &conv, 10);
-    if (conv == (const char*)obj->stringval) {
-      testError(conn, NULL, VIR_ERR_XML_ERROR, _("node cpu mhz"));
-      goto error;
+
+    obj = xmlXPathEval(BAD_CAST "string(/node/cpu/cores[1])", ctxt);
+    if ((obj != NULL) && (obj->type == XPATH_STRING) &&
+        (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
+        char *conv = NULL;
+        nodeInfo->cores = strtol((const char*)obj->stringval, &conv, 10);
+        if (conv == (const char*)obj->stringval) {
+            testError(conn, NULL, VIR_ERR_XML_ERROR, _("node cpu cores"));
+            goto error;
+        }
+        xmlXPathFreeObject(obj);
     }
-    xmlXPathFreeObject(obj);
-  }
-  obj = xmlXPathEval(BAD_CAST "string(/node/cpu/model[1])", ctxt);
-  if ((obj != NULL) && (obj->type == XPATH_STRING) &&
-      (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
-    strncpy(nodeInfo->model, (const char *)obj->stringval, sizeof(nodeInfo->model)-1);
-    nodeInfo->model[sizeof(nodeInfo->model)-1] = '\0';
-    xmlXPathFreeObject(obj);
-  }
 
-  obj = xmlXPathEval(BAD_CAST "string(/node/memory[1])", ctxt);
-  if ((obj != NULL) && (obj->type == XPATH_STRING) &&
-      (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
-    char *conv = NULL;
-    nodeInfo->memory = strtol((const char*)obj->stringval, &conv, 10);
-    if (conv == (const char*)obj->stringval) {
-      testError(conn, NULL, VIR_ERR_XML_ERROR, _("node memory"));
-      goto error;
+    obj = xmlXPathEval(BAD_CAST "string(/node/cpu/threads[1])", ctxt);
+    if ((obj != NULL) && (obj->type == XPATH_STRING) &&
+        (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
+        char *conv = NULL;
+        nodeInfo->threads = strtol((const char*)obj->stringval, &conv, 10);
+        if (conv == (const char*)obj->stringval) {
+            testError(conn, NULL, VIR_ERR_XML_ERROR, _("node cpu threads"));
+            goto error;
+        }
+        xmlXPathFreeObject(obj);
+    }
+    nodeInfo->cpus = nodeInfo->cores * nodeInfo->threads * nodeInfo->sockets * nodeInfo->nodes;
+    obj = xmlXPathEval(BAD_CAST "string(/node/cpu/active[1])", ctxt);
+    if ((obj != NULL) && (obj->type == XPATH_STRING) &&
+        (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
+        char *conv = NULL;
+        unsigned int active = strtol((const char*)obj->stringval, &conv, 10);    
+        if (conv == (const char*)obj->stringval) {
+            testError(conn, NULL, VIR_ERR_XML_ERROR, _("node active cpu"));
+            goto error;
+        }
+        if (active < nodeInfo->cpus) {
+            nodeInfo->cpus = active;
+        }
+        xmlXPathFreeObject(obj);
+    }
+    obj = xmlXPathEval(BAD_CAST "string(/node/cpu/mhz[1])", ctxt);
+    if ((obj != NULL) && (obj->type == XPATH_STRING) &&
+        (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
+        char *conv = NULL;
+        nodeInfo->mhz = strtol((const char*)obj->stringval, &conv, 10);
+        if (conv == (const char*)obj->stringval) {
+            testError(conn, NULL, VIR_ERR_XML_ERROR, _("node cpu mhz"));
+            goto error;
+        }
+        xmlXPathFreeObject(obj);
+    }
+    obj = xmlXPathEval(BAD_CAST "string(/node/cpu/model[1])", ctxt);
+    if ((obj != NULL) && (obj->type == XPATH_STRING) &&
+        (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
+        strncpy(nodeInfo->model, (const char *)obj->stringval, sizeof(nodeInfo->model)-1);
+        nodeInfo->model[sizeof(nodeInfo->model)-1] = '\0';
+        xmlXPathFreeObject(obj);
     }
-    xmlXPathFreeObject(obj);
-  }
 
-  obj = xmlXPathEval(BAD_CAST "/node/domain", ctxt);
-  if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
-      (obj->nodesetval == NULL)) {
-    testError(NULL, NULL, VIR_ERR_XML_ERROR, _("node domain list"));
-    goto error;
-  }
+    obj = xmlXPathEval(BAD_CAST "string(/node/memory[1])", ctxt);
+    if ((obj != NULL) && (obj->type == XPATH_STRING) &&
+        (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
+        char *conv = NULL;
+        nodeInfo->memory = strtol((const char*)obj->stringval, &conv, 10);
+        if (conv == (const char*)obj->stringval) {
+            testError(conn, NULL, VIR_ERR_XML_ERROR, _("node memory"));
+            goto error;
+        }
+        xmlXPathFreeObject(obj);
+    }
 
-  for (i = 0 ; i < obj->nodesetval->nodeNr ; i++) {
-    xmlChar *domFile = xmlGetProp(obj->nodesetval->nodeTab[i], BAD_CAST "file");
-    char *absFile = testBuildFilename(file, (const char *)domFile);
-    free(domFile);
-    if (!absFile) {
-      testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("resolving domain filename"));
-      goto error;
+    obj = xmlXPathEval(BAD_CAST "/node/domain", ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
+        (obj->nodesetval == NULL)) {
+        testError(NULL, NULL, VIR_ERR_XML_ERROR, _("node domain list"));
+        goto error;
     }
-    if (testLoadDomainFromFile(conn, i, absFile) != 0) {
-      free(absFile);
-      goto error;
+
+    for (i = 0 ; i < obj->nodesetval->nodeNr ; i++) {
+        xmlChar *domFile = xmlGetProp(obj->nodesetval->nodeTab[i], BAD_CAST "file");
+        char *absFile = testBuildFilename(file, (const char *)domFile);
+        int domid = nextDomID++;
+        free(domFile);
+        if (!absFile) {
+            testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("resolving domain filename"));
+            goto error;
+        }
+        if (testLoadDomainFromFile(conn, domid, absFile) != 0) {
+            free(absFile);
+            goto error;
+        }
+        free(absFile);
+        node->connections[connid].numDomains++;
     }
-    free(absFile);
-    node->connections[connid].numDomains++;
-  }
 
-  xmlXPathFreeObject(obj);
-  xmlFreeDoc(xml);
+    xmlXPathFreeObject(obj);
+    xmlFreeDoc(xml);
 
-  return 0;
+    return (0);
 
  error:
-  if (node->connections[connid].active) {
-    for (i = 0 ; i <node->connections[connid].numDomains ; i++) {
-      node->connections[connid].domains[i].active = 0;
+    if (node->connections[connid].active) {
+        for (i = 0 ; i <node->connections[connid].numDomains ; i++) {
+            node->connections[connid].domains[i].active = 0;
+        }
+        node->connections[connid].numDomains = 0;
+        node->connections[connid].active = 0;
     }
-    node->connections[connid].numDomains = 0;
-    node->connections[connid].active = 0;
-  }
-  if (obj)
-    xmlXPathFreeObject(obj);
-  if (xml)
-    xmlFreeDoc(xml);
-  if (fd != -1)
-    close(fd);
-  return -1;
+    if (obj)
+        xmlXPathFreeObject(obj);
+    if (xml)
+        xmlFreeDoc(xml);
+    if (fd != -1)
+        close(fd);
+    return (-1);
 }
 
 static int getNextConnection(void) {
-  int i;
-  if (node == NULL) {
-    node = calloc(1, sizeof(testNode));
-    if (!node) {
-      testError(NULL, NULL, VIR_ERR_NO_MEMORY, _("allocating node"));
-      return -1;
+    int i;
+    if (node == NULL) {
+        node = calloc(1, sizeof(testNode));
+        nextDomID = 1;
+        if (!node) {
+            testError(NULL, NULL, VIR_ERR_NO_MEMORY, _("allocating node"));
+            return (-1);
+        }
+    }
+
+    for (i = 0 ; i < MAX_CONNECTIONS ; i++) {
+        if (!node->connections[i].active) {
+            return (i);
+        }
     }
-  }
+    return (-1);
+}
 
-  for (i = 0 ; i < MAX_CONNECTIONS ; i++) {
-    if (!node->connections[i].active) {
-      return i;
+static int getDomainIndex(virDomainPtr domain) {
+    int i;
+    testCon *con;
+    con = &node->connections[domain->conn->handle];
+    for (i = 0 ; i < MAX_DOMAINS ; i++) {
+        if (domain->handle >= 0) {
+            if (domain->handle == con->domains[i].handle)
+                return (i);
+        } else {
+            if (!strcmp(domain->name, con->domains[i].name))
+                return (i);
+        }
     }
-  }
-  return -1;
+    return (-1);
 }
 
 int testOpen(virConnectPtr conn,
              const char *name,
              int flags)
 {
-  xmlURIPtr uri;
-  int ret, connid;
-
-  if (!name) {
-    return -1;
-  }
-
-  uri = xmlParseURI(name);
-  if (uri == NULL) {
-    if (!(flags & VIR_DRV_OPEN_QUIET))
-      testError(conn, NULL, VIR_ERR_NO_SUPPORT, name);
-    return(-1);
-  }
-
-  if (!uri->scheme ||
-      strcmp(uri->scheme, "test") ||
-      !uri->path) {
-    xmlFreeURI(uri);
-    return -1;
-  }
+    xmlURIPtr uri;
+    int ret, connid;
 
+    if (!name) {
+        return (-1);
+    }
 
-  if ((connid = getNextConnection()) < 0) {
-    testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("too many connections"));
-    return -1;
-  }
+    uri = xmlParseURI(name);
+    if (uri == NULL) {
+        if (!(flags & VIR_DRV_OPEN_QUIET))
+            testError(conn, NULL, VIR_ERR_NO_SUPPORT, name);
+        return(-1);
+    }
 
-  if (!strcmp(uri->path, "/default")) {
-    ret = testOpenDefault(conn,
-                         connid);
-  } else {
-    ret = testOpenFromFile(conn,
-                          connid,
-                          uri->path);
-  }
+    if (!uri->scheme ||
+        strcmp(uri->scheme, "test") ||
+        !uri->path) {
+        xmlFreeURI(uri);
+        return (-1);
+    }
 
-  xmlFreeURI(uri);
 
-  return (ret);
+    if ((connid = getNextConnection()) < 0) {
+        testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("too many connections"));
+        return (-1);
+    }
+
+    if (!strcmp(uri->path, "/default")) {
+        ret = testOpenDefault(conn,
+                              connid);
+    } else {
+        ret = testOpenFromFile(conn,
+                               connid,
+                               uri->path);
+    }
+
+    xmlFreeURI(uri);
+
+    return (ret);
 }
 
 int testClose(virConnectPtr conn)
 {
-  testCon *con = &node->connections[conn->handle];
-  con->active = 0;
-  conn->handle = -1;
-  memset(con, 0, sizeof(testCon));
-  return 0;
+    testCon *con = &node->connections[conn->handle];
+    con->active = 0;
+    conn->handle = -1;
+    memset(con, 0, sizeof(testCon));
+    return (0);
 }
 
 int testGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
                    unsigned long *hvVer)
 {
-  *hvVer = 2;
-  return 0;
+    *hvVer = 2;
+    return (0);
 }
 
 int testNodeGetInfo(virConnectPtr conn,
                     virNodeInfoPtr info)
 {
-  testCon *con = &node->connections[conn->handle];
-  memcpy(info, &con->nodeInfo, sizeof(virNodeInfo));
-  return 0;
+    testCon *con = &node->connections[conn->handle];
+    memcpy(info, &con->nodeInfo, sizeof(virNodeInfo));
+    return (0);
 }
 
 int testNumOfDomains(virConnectPtr conn)
 {
-  testCon *con = &node->connections[conn->handle];
-  return con->numDomains;
+    int numActive = 0, i;
+    testCon *con = &node->connections[conn->handle];
+    for (i = 0 ; i < MAX_DOMAINS ; i++) {
+        if (!con->domains[i].active ||
+            con->domains[i].info.state == VIR_DOMAIN_SHUTOFF)
+            continue;
+        numActive++;
+    }
+    return (numActive);
 }
 
 virDomainPtr
 testDomainCreateLinux(virConnectPtr conn, const char *xmlDesc,
-                     unsigned int flags ATTRIBUTE_UNUSED)
+                      unsigned int flags ATTRIBUTE_UNUSED)
 {
-  testCon *con;
-  int i;
-  virDomainPtr dom;
+    testCon *con;
+    int domid, handle = -1, i;
+    virDomainPtr dom;
 
-  if (!VIR_IS_CONNECT(conn)) {
-    testError(conn, NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
-    return (NULL);
-  }
-  if (xmlDesc == NULL) {
-    testError(conn, NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
-    return (NULL);
-  }
-  if (conn->flags & VIR_CONNECT_RO) {
-    testError(conn, NULL, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-    return (NULL);
-  }
-  
-  con = &node->connections[conn->handle];
-
-  for (i = 0 ; i < MAX_DOMAINS ; i++) {
-    if (!con->domains[i].active) {
-      if (testLoadDomainFromDoc(conn, i, xmlDesc) < 0)
-       return NULL;
-      dom = virGetDomain(conn, con->domains[i].name, con->domains[i].uuid);
-      if (dom == NULL) {
-       testError(conn, NULL, VIR_ERR_NO_MEMORY, _("allocating domain"));
-       return NULL;
-      }
-      con->numDomains++;
-      return dom;
-    }
-  }
+    if (!VIR_IS_CONNECT(conn)) {
+        testError(conn, NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+    if (xmlDesc == NULL) {
+        testError(conn, NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+    if (conn->flags & VIR_CONNECT_RO) {
+        testError(conn, NULL, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        return (NULL);
+    }
   
-  testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("too many domains"));
-  return (NULL);
+    con = &node->connections[conn->handle];
+
+    if (con->numDomains == MAX_DOMAINS) {
+        testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("too many domains"));
+        return (NULL);
+    }
+
+    domid = nextDomID++;
+    if (testLoadDomainFromDoc(conn, domid, xmlDesc) < 0)
+        return (NULL);
+    for (i = 0 ; i < MAX_DOMAINS ; i++) {
+        if (con->domains[i].handle == domid) {
+            handle = i;
+            break;
+        }
+    }
+    dom = virGetDomain(conn, con->domains[handle].name, con->domains[handle].uuid);
+    if (dom == NULL) {
+        testError(conn, NULL, VIR_ERR_NO_MEMORY, _("allocating domain"));
+        return (NULL);
+    }
+    con->numDomains++;
+    return (dom);
 }
 
 
 virDomainPtr testLookupDomainByID(virConnectPtr conn,
                                   int id)
 {
-  testCon *con = &node->connections[conn->handle];
-  virDomainPtr dom;
-
-  if (!con->domains[id].active) {
-    return NULL;
-  }
-
-  dom = virGetDomain(conn, con->domains[id].name, con->domains[id].uuid);
-  if (dom == NULL) {
-    testError(conn, NULL, VIR_ERR_NO_MEMORY, _("allocating domain"));
-    return(NULL);
-  }
-  dom->handle = id;
-  return dom;
+    testCon *con = &node->connections[conn->handle];
+    virDomainPtr dom;
+    int i, idx = -1;
+
+    for (i = 0 ; i < MAX_DOMAINS ; i++) {
+        if (con->domains[i].active &&
+            con->domains[i].handle == id) {
+            idx = i;
+            break;
+        }
+    }
+
+    if (idx < 0) {
+        return(NULL);
+    }
+
+    dom = virGetDomain(conn, con->domains[idx].name, con->domains[idx].uuid);
+    if (dom == NULL) {
+        testError(conn, NULL, VIR_ERR_NO_MEMORY, _("allocating domain"));
+        return(NULL);
+    }
+    dom->handle = id;
+    return (dom);
 }
 
 virDomainPtr testLookupDomainByUUID(virConnectPtr conn,
                                     const unsigned char *uuid)
 {
-  testCon *con = &node->connections[conn->handle];
-  virDomainPtr dom = NULL;
-  int i, id = -1;
-  for (i = 0 ; i < MAX_DOMAINS ; i++) {
-    if (con->domains[i].active &&
-       memcmp(uuid, con->domains[i].uuid, 16) == 0) {
-      id = i;
-      break;
-    }
-  }
-  if (id >= 0) {
-    dom = virGetDomain(conn, con->domains[id].name, con->domains[id].uuid);
-    if (dom == NULL) {
-      testError(conn, NULL, VIR_ERR_NO_MEMORY, _("allocating domain"));
-      return(NULL);
+    testCon *con = &node->connections[conn->handle];
+    virDomainPtr dom = NULL;
+    int i, idx = -1;
+    for (i = 0 ; i < MAX_DOMAINS ; i++) {
+        if (con->domains[i].active &&
+            memcmp(uuid, con->domains[i].uuid, 16) == 0) {
+            idx = i;
+            break;
+        }
     }
-    dom->handle = id;
-  }
-  return dom;
+    if (idx >= 0) {
+        dom = virGetDomain(conn, con->domains[idx].name, con->domains[idx].uuid);
+        if (dom == NULL) {
+            testError(conn, NULL, VIR_ERR_NO_MEMORY, _("allocating domain"));
+            return(NULL);
+        }
+        dom->handle = con->domains[idx].handle;
+    }
+    return (dom);
 }
 
 virDomainPtr testLookupDomainByName(virConnectPtr conn,
                                     const char *name)
 {
-  testCon *con = &node->connections[conn->handle];
-  virDomainPtr dom = NULL;
-  int i, id = -1;
-  for (i = 0 ; i < MAX_DOMAINS ; i++) {
-    if (con->domains[i].active &&
-       strcmp(name, con->domains[i].name) == 0) {
-      id = i;
-      break;
-    }
-  }
-  if (id >= 0) {
-    dom = virGetDomain(conn, con->domains[id].name, con->domains[id].uuid);
-    if (dom == NULL) {
-      testError(conn, NULL, VIR_ERR_NO_MEMORY, _("allocating domain"));
-      return(NULL);
+    testCon *con = &node->connections[conn->handle];
+    virDomainPtr dom = NULL;
+    int i, idx = -1;
+    for (i = 0 ; i < MAX_DOMAINS ; i++) {
+        if (con->domains[i].active &&
+            strcmp(name, con->domains[i].name) == 0) {
+            idx = i;
+            break;
+        }
     }
-    dom->handle = id;
-  }
-  return dom;
+    if (idx >= 0) {
+        dom = virGetDomain(conn, con->domains[idx].name, con->domains[idx].uuid);
+        if (dom == NULL) {
+            testError(conn, NULL, VIR_ERR_NO_MEMORY, _("allocating domain"));
+            return(NULL);
+        }
+        dom->handle = con->domains[idx].handle;
+    }
+    return (dom);
 }
 
 int testListDomains (virConnectPtr conn,
                      int *ids,
                      int maxids)
 {
-  testCon *con = &node->connections[conn->handle];
-  int n, i;
-
-  for (i = 0, n = 0 ; i < MAX_DOMAINS && n < maxids ; i++) {
-    if (con->domains[i].active) {
-      ids[n++] = i;
+    testCon *con = &node->connections[conn->handle];
+    int n, i;
+
+    for (i = 0, n = 0 ; i < MAX_DOMAINS && n < maxids ; i++) {
+        if (con->domains[i].active &&
+            con->domains[i].info.state != VIR_DOMAIN_SHUTOFF) {
+            ids[n++] = con->domains[i].handle;
+        }
     }
-  }
-  return n;
+    return (n);
 }
 
 int testDestroyDomain (virDomainPtr domain)
 {
-  testCon *con;
-  if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-    testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
-             __FUNCTION__);
-    return(-1);
-  }
-  if (domain->conn->flags & VIR_CONNECT_RO) {
-    testError(domain->conn, domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-    return (-1);
-  }
-  
-  con = &node->connections[domain->conn->handle];
-  con->domains[domain->handle].active = 0;
-  return (0);
+    testCon *con;
+    int domidx;
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
+        ((domidx = getDomainIndex(domain)) < 0)) {
+        testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
+                  __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        testError(domain->conn, domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        return (-1);
+    }
+
+    con = &node->connections[domain->conn->handle];
+    con->domains[domidx].active = 0;
+    return (0);
 }
 
 int testResumeDomain (virDomainPtr domain)
 {
-  testCon *con;
-  if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-    testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
-             __FUNCTION__);
-    return(-1);
-  }
-  if (domain->conn->flags & VIR_CONNECT_RO) {
-    testError(domain->conn, domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-    return (-1);
-  }
+    testCon *con;
+    int domidx;
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
+        ((domidx = getDomainIndex(domain)) < 0)) {
+        testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
+                  __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        testError(domain->conn, domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        return (-1);
+    }
 
-  con = &node->connections[domain->conn->handle];
-  con->domains[domain->handle].info.state = VIR_DOMAIN_RUNNING;
-  return 0;
+    con = &node->connections[domain->conn->handle];
+    con->domains[domidx].info.state = VIR_DOMAIN_RUNNING;
+    return (0);
 }
 
 int testPauseDomain (virDomainPtr domain)
 {
-  testCon *con;
-  if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-    testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
-             __FUNCTION__);
-    return(-1);
-  }
-  if (domain->conn->flags & VIR_CONNECT_RO) {
-    testError(domain->conn, domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-    return (-1);
-  }
+    testCon *con;\
+    int domidx;
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
+        ((domidx = getDomainIndex(domain)) < 0)) {
+        testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
+                  __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        testError(domain->conn, domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        return (-1);
+    }
 
-  con = &node->connections[domain->conn->handle];
-  con->domains[domain->handle].info.state = VIR_DOMAIN_PAUSED;
-  return (0);
+    con = &node->connections[domain->conn->handle];
+    con->domains[domidx].info.state = VIR_DOMAIN_PAUSED;
+    return (0);
 }
 
 /* We don't do an immediate shutdown. We basically pretend that
@@ -880,242 +1027,361 @@ int testPauseDomain (virDomainPtr domain)
    will check to see if shutdown ought to be marked complete. */
 int testShutdownDomain (virDomainPtr domain)
 {
-  testCon *con;
-  struct timeval tv;
-  if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-    testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
-             __FUNCTION__);
-    return (-1);
-  }
-  if (domain->conn->flags & VIR_CONNECT_RO) {
-    testError(domain->conn, domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-    return (-1);
-  }
+    testCon *con;
+    int domidx;
+    struct timeval tv;
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
+        ((domidx = getDomainIndex(domain)) < 0)) {
+        testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
+                  __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        testError(domain->conn, domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        return (-1);
+    }
 
-  con = &node->connections[domain->conn->handle];
+    con = &node->connections[domain->conn->handle];
 
-  if (gettimeofday(&tv, NULL) < 0) {
-    testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("getting time of day"));
-    return (-1);
-  }
+    if (gettimeofday(&tv, NULL) < 0) {
+        testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("getting time of day"));
+        return (-1);
+    }
 
-  con->domains[domain->handle].info.state = VIR_DOMAIN_SHUTDOWN;
-  con->domains[domain->handle].onRestart = VIR_DOMAIN_DESTROY;
-  con->domains[domain->handle].shutdownStartedAt = tv.tv_sec;
-  return (0);
+    con->domains[domidx].info.state = VIR_DOMAIN_SHUTOFF;
+    domain->handle = -1;
+    con->domains[domidx].handle = -1;
+
+    return (0);
 }
 
 /* Similar behaviour as shutdown */
 int testRebootDomain (virDomainPtr domain, virDomainRestart action)
 {
-  testCon *con;
-  struct timeval tv;
-  if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-    testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
-             __FUNCTION__);
-    return(-1);
-  }
-  if (domain->conn->flags & VIR_CONNECT_RO) {
-    testError(domain->conn, domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-    return (-1);
-  }
+    testCon *con;
+    int domidx;
+    struct timeval tv;
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
+        ((domidx = getDomainIndex(domain)) < 0)) {
+        testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
+                  __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        testError(domain->conn, domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        return (-1);
+    }
 
-  con = &node->connections[domain->conn->handle];
+    con = &node->connections[domain->conn->handle];
 
-  if (gettimeofday(&tv, NULL) < 0) {
-    testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("getting time of day"));
-    return (-1);
-  }
+    if (gettimeofday(&tv, NULL) < 0) {
+        testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("getting time of day"));
+        return (-1);
+    }
+
+    if (!action)
+        action = VIR_DOMAIN_RESTART;
+
+    con->domains[domidx].info.state = VIR_DOMAIN_SHUTDOWN;
+    switch (action) {
+    case VIR_DOMAIN_DESTROY:
+        con->domains[domidx].info.state = VIR_DOMAIN_SHUTOFF;
+        break;
+
+    case VIR_DOMAIN_RESTART:
+        con->domains[domidx].info.state = VIR_DOMAIN_RUNNING;
+        break;
+
+    case VIR_DOMAIN_PRESERVE:
+        con->domains[domidx].info.state = VIR_DOMAIN_SHUTOFF;
+        break;
+
+    case VIR_DOMAIN_RENAME_RESTART:
+        con->domains[domidx].info.state = VIR_DOMAIN_RUNNING;
+        break;
 
-  if (!action)
-    action = VIR_DOMAIN_RESTART;
+    default:
+        con->domains[domidx].info.state = VIR_DOMAIN_SHUTOFF;
+        break;
+    }
+    domain->handle = -1;
+    con->domains[domidx].handle = -1;
 
-  con->domains[domain->handle].info.state = VIR_DOMAIN_SHUTDOWN;
-  con->domains[domain->handle].onRestart = action;
-  con->domains[domain->handle].shutdownStartedAt = tv.tv_sec;
-  return (0);
+    return (0);
 }
 
 int testGetDomainInfo (virDomainPtr domain,
                        virDomainInfoPtr info)
 {
-  struct timeval tv;
-  testCon *con;
-  if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-    testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
-             __FUNCTION__);
-    return(-1);
-  }
-
-  con = &node->connections[domain->conn->handle];
-
-  if (gettimeofday(&tv, NULL) < 0) {
-    testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("getting time of day"));
-    return (-1);
-  }
-
-  /* Check to see if there is an in-progresss shutdown/reboot that
-     needs to be marked completed now */
-  if (con->domains[domain->handle].info.state == VIR_DOMAIN_SHUTDOWN &&
-      (tv.tv_sec - con->domains[domain->handle].shutdownStartedAt) > SHUTDOWN_DURATION) {
-
-      switch (con->domains[domain->handle].onRestart) {
-      case VIR_DOMAIN_DESTROY:
-       con->domains[domain->handle].info.state = VIR_DOMAIN_SHUTOFF;
-       break;
-
-      case VIR_DOMAIN_RESTART:
-       con->domains[domain->handle].info.state = VIR_DOMAIN_RUNNING;
-       break;
-
-      case VIR_DOMAIN_PRESERVE:
-       con->domains[domain->handle].info.state = VIR_DOMAIN_SHUTOFF;
-       break;
-
-      case VIR_DOMAIN_RENAME_RESTART:
-       con->domains[domain->handle].info.state = VIR_DOMAIN_RUNNING;
-       break;
-
-      default:
-       con->domains[domain->handle].info.state = VIR_DOMAIN_SHUTOFF;
-       break;
-    }
-  }
-
-  if (con->domains[domain->handle].info.state == VIR_DOMAIN_SHUTOFF) {
-    con->domains[domain->handle].info.cpuTime = 0;
-    con->domains[domain->handle].info.memory = 0;
-  } else {
-    con->domains[domain->handle].info.cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
-  }
-  memcpy(info, &con->domains[domain->handle].info, sizeof(virDomainInfo));
-  return (0);
+    struct timeval tv;
+    testCon *con;
+    int domidx;
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
+        ((domidx = getDomainIndex(domain)) < 0)) {
+        testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
+                  __FUNCTION__);
+        return (-1);
+    }
+
+    con = &node->connections[domain->conn->handle];
+
+    if (gettimeofday(&tv, NULL) < 0) {
+        testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("getting time of day"));
+        return (-1);
+    }
+
+    if (con->domains[domidx].info.state == VIR_DOMAIN_SHUTOFF) {
+        con->domains[domidx].info.cpuTime = 0;
+        con->domains[domidx].info.memory = 0;
+    } else {
+        con->domains[domidx].info.cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
+    }
+    memcpy(info, &con->domains[domidx].info, sizeof(virDomainInfo));
+    return (0);
 }
 
 char *testGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) {
-  return strdup("linux");
+    return strdup("linux");
 }
 
 unsigned long testGetMaxMemory(virDomainPtr domain) {
-  testCon *con;
-  if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-    testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
-             __FUNCTION__);
-    return(-1);
-  }
-  
-  con = &node->connections[domain->conn->handle];
-  return con->domains[domain->handle].info.maxMem;
+    testCon *con;
+    int domidx;
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
+        ((domidx = getDomainIndex(domain)) < 0)) {
+        testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
+                  __FUNCTION__);
+        return (-1);
+    }
+
+    con = &node->connections[domain->conn->handle];
+    return con->domains[domidx].info.maxMem;
 }
 
-int testSetMaxMemory (virDomainPtr domain,
-                      unsigned long memory)
+int testSetMaxMemory(virDomainPtr domain,
+                     unsigned long memory)
 {
-  testCon *con;
-  if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-    testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
-             __FUNCTION__);
-    return(-1);
-  }
-  if (domain->conn->flags & VIR_CONNECT_RO) {
-    testError(domain->conn, domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-    return (-1);
-  }
+    testCon *con;
+    int domidx;
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
+        ((domidx = getDomainIndex(domain)) < 0)) {
+        testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
+                  __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        testError(domain->conn, domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        return (-1);
+    }
 
-  con = &node->connections[domain->conn->handle];
-  /* XXX validate not over host memory wrt to other domains */
-  con->domains[domain->handle].info.maxMem = memory;
-  return (0);
+    con = &node->connections[domain->conn->handle];
+    /* XXX validate not over host memory wrt to other domains */
+    con->domains[domidx].info.maxMem = memory;
+    return (0);
 }
 
-int testSetMemory (virDomainPtr domain,
-                  unsigned long memory)
+int testSetMemory(virDomainPtr domain,
+                  unsigned long memory)
 {
-  testCon *con;
-  if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-    testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
-             __FUNCTION__);
-    return(-1);
-  }
-  if (domain->conn->flags & VIR_CONNECT_RO) {
-    testError(domain->conn, domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-    return (-1);
-  }
+    testCon *con;
+    int domidx;
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
+        ((domidx = getDomainIndex(domain)) < 0)) {
+        testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
+                  __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        testError(domain->conn, domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        return (-1);
+    }
 
-  con = &node->connections[domain->conn->handle];
+    con = &node->connections[domain->conn->handle];
 
-  if (memory > con->domains[domain->handle].info.maxMem) {
-    testError(domain->conn, domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
-    return (-1);
-  }
+    if (memory > con->domains[domidx].info.maxMem) {
+        testError(domain->conn, domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
 
-  con->domains[domain->handle].info.memory = memory;
-  return (0);
+    con->domains[domidx].info.memory = memory;
+    return (0);
 }
 
 int testSetVcpus(virDomainPtr domain,
-                unsigned int nrCpus) {
-  testCon *con;
-
-  if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-    testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
-             __FUNCTION__);
-    return(-1);
-  }
-  if (domain->conn->flags & VIR_CONNECT_RO) {
-    testError(domain->conn, domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-    return (-1);
-  }
+                 unsigned int nrCpus) {
+    testCon *con;
+    int domidx;
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
+        ((domidx = getDomainIndex(domain)) < 0)) {
+        testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
+                  __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        testError(domain->conn, domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        return (-1);
+    }
 
-  con = &node->connections[domain->conn->handle];
+    con = &node->connections[domain->conn->handle];
 
-  /* We allow more cpus in guest than host */
-  if (nrCpus > 32) {
-    testError(domain->conn, domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
-    return (-1);
-  }
+    /* We allow more cpus in guest than host */
+    if (nrCpus > 32) {
+        testError(domain->conn, domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
 
-  con->domains[domain->handle].info.nrVirtCpu = nrCpus;
-  return (0);
+    con->domains[domidx].info.nrVirtCpu = nrCpus;
+    return (0);
 }
 
 char * testDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED)
 {
-  virBufferPtr buf;
-  char *xml;
-  unsigned char *uuid;
-  testCon *con;
-  if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-    testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
-             __FUNCTION__);
-    return(NULL);
-  }
-  
-  con = &node->connections[domain->conn->handle];
-  
-  if (!(buf = virBufferNew(4000))) {
-    return (NULL);
-  }
-  
-  virBufferVSprintf(buf, "<domain type='test' id='%d'>\n", domain->handle);
-  virBufferVSprintf(buf, "  <name>%s</name>\n", domain->name);
-  uuid = domain->uuid;
-  virBufferVSprintf(buf,
-                   "  <uuid>%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x</uuid>\n",
-                   uuid[0], uuid[1], uuid[2], uuid[3],
-                   uuid[4], uuid[5], uuid[6], uuid[7],
-                   uuid[8], uuid[9], uuid[10], uuid[11],
-                   uuid[12], uuid[13], uuid[14], uuid[15]);
-  
-  virBufferVSprintf(buf, "  <memory>%d</memory>\n", con->domains[domain->handle].info.maxMem);
-  virBufferVSprintf(buf, "  <vcpu>%d</vcpu>\n", con->domains[domain->handle].info.nrVirtCpu);
-  virBufferVSprintf(buf, "  <on_reboot>%s</on_reboot>\n", testRestartFlagToString(con->domains[domain->handle].onReboot));
-  virBufferVSprintf(buf, "  <on_poweroff>%s</on_poweroff>\n", testRestartFlagToString(con->domains[domain->handle].onPoweroff));
-  virBufferVSprintf(buf, "  <on_crash>%s</on_crash>\n", testRestartFlagToString(con->domains[domain->handle].onCrash));
-  
-  virBufferAdd(buf, "</domain>\n", -1);
-  
-  xml = buf->content;
-  free(buf);
-  return xml;
+    virBufferPtr buf;
+    char *xml;
+    unsigned char *uuid;
+    testCon *con;
+    int domidx;
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
+        ((domidx = getDomainIndex(domain)) < 0)) {
+        testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
+                  __FUNCTION__);
+        return (NULL);
+    }
+
+    con = &node->connections[domain->conn->handle];
+
+    if (!(buf = virBufferNew(4000))) {
+        return (NULL);
+    }
+
+    virBufferVSprintf(buf, "<domain type='test' id='%d'>\n", domain->handle);
+    virBufferVSprintf(buf, "  <name>%s</name>\n", domain->name);
+    uuid = domain->uuid;
+    virBufferVSprintf(buf,
+                      "  <uuid>%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x</uuid>\n",
+                      uuid[0], uuid[1], uuid[2], uuid[3],
+                      uuid[4], uuid[5], uuid[6], uuid[7],
+                      uuid[8], uuid[9], uuid[10], uuid[11],
+                      uuid[12], uuid[13], uuid[14], uuid[15]);
+
+    virBufferVSprintf(buf, "  <memory>%d</memory>\n", con->domains[domidx].info.maxMem);
+    virBufferVSprintf(buf, "  <vcpu>%d</vcpu>\n", con->domains[domidx].info.nrVirtCpu);
+    virBufferVSprintf(buf, "  <on_reboot>%s</on_reboot>\n", testRestartFlagToString(con->domains[domidx].onReboot));
+    virBufferVSprintf(buf, "  <on_poweroff>%s</on_poweroff>\n", testRestartFlagToString(con->domains[domidx].onPoweroff));
+    virBufferVSprintf(buf, "  <on_crash>%s</on_crash>\n", testRestartFlagToString(con->domains[domidx].onCrash));
+
+    virBufferAdd(buf, "</domain>\n", -1);
+
+    xml = buf->content;
+    free(buf);
+
+    return (xml);
 }
+
+
+int testNumOfDefinedDomains(virConnectPtr conn) {
+    int numInactive = 0, i;
+    testCon *con = &node->connections[conn->handle];
+    for (i = 0 ; i < MAX_DOMAINS ; i++) {
+        if (!con->domains[i].active ||
+            con->domains[i].info.state != VIR_DOMAIN_SHUTOFF)
+            continue;
+        numInactive++;
+    }
+    return (numInactive);
+}
+
+int testListDefinedDomains(virConnectPtr conn,
+                           const char **names,
+                           int maxnames) {
+    testCon *con = &node->connections[conn->handle];
+    int n = 0, i;
+
+    for (i = 0, n = 0 ; i < MAX_DOMAINS && n < maxnames ; i++) {
+        if (con->domains[i].active &&
+            con->domains[i].info.state == VIR_DOMAIN_SHUTOFF) {
+            names[n++] = strdup(con->domains[i].name);
+        }
+    }
+    return (n);
+}
+
+virDomainPtr testDomainDefineXML(virConnectPtr conn,
+                                 const char *doc) {
+    int ret;
+    xmlDocPtr xml;
+    int domid;
+
+    if (!(xml = xmlReadDoc(BAD_CAST doc, "domain.xml", NULL,
+                           XML_PARSE_NOENT | XML_PARSE_NONET |
+                           XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
+        testError(NULL, NULL, VIR_ERR_XML_ERROR, _("domain"));
+        return (NULL);
+    }
+
+    domid = nextDomID++;
+    ret = testLoadDomain(conn, domid, xml);
+
+    xmlFreeDoc(xml);
+
+    if (ret < 0)
+        return (NULL);
+
+    return testLookupDomainByID(conn, domid);
+}
+
+int testDomainCreate(virDomainPtr domain) {
+    testCon *con;
+    int domidx;
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
+        ((domidx = getDomainIndex(domain)) < 0)) {
+        testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
+                  __FUNCTION__);
+        return (-1);
+    }
+
+    con = &node->connections[domain->conn->handle];
+
+    if (con->domains[domidx].info.state != VIR_DOMAIN_SHUTOFF) {
+        testError(domain->conn, domain, VIR_ERR_INTERNAL_ERROR,
+                  _("Domain is already running"));
+        return (-1);
+    }
+
+    domain->handle = con->domains[domidx].handle = nextDomID++;
+    con->domains[domidx].info.state = VIR_DOMAIN_RUNNING;
+
+    return (0);
+}
+
+int testDomainUndefine(virDomainPtr domain) {
+    testCon *con;
+    int domidx;
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
+        ((domidx = getDomainIndex(domain)) < 0)) {
+        testError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
+                  __FUNCTION__);
+        return (-1);
+    }
+
+    con = &node->connections[domain->conn->handle];
+
+    if (con->domains[domidx].info.state != VIR_DOMAIN_SHUTOFF) {
+        testError(domain->conn, domain, VIR_ERR_INTERNAL_ERROR,
+                  _("Domain is still running"));
+        return (-1);
+    }
+
+    con->domains[domidx].active = 0;
+
+    return (0);
+}
+
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
index 0bbe93a796fc107dadc957a56e959b4c4570e911..aa819af4ea59551ca7f98c3ba5fc337a8370f8d5 100644 (file)
@@ -1,15 +1,28 @@
 /*
  * test.h: A "mock" hypervisor for use by application unit tests
  *
- * Copyright (C) 2006 Red Hat, Inc.
+ * Copyright (C) 2006-2006 Red Hat, Inc.
+ * Copyright (C) 2006  Daniel P. Berrange
  *
- * See COPYING.LIB for the License of this software
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
  *
  * Daniel Berrange <berrange@redhat.com>
  */
 
-#ifndef __VIR_TEST_SIMPLE_INTERNAL_H__
-#define __VIR_TEST_SIMPLE_INTERNAL_H__
+#ifndef __VIR_TEST_INTERNAL_H__
+#define __VIR_TEST_INTERNAL_H__
 
 #include <libvirt/virterror.h>
 
 extern "C" {
 #endif
 
-void testRegister(void);
-int testOpen(virConnectPtr conn,
-             const char *name,
-             int flags);
-int testClose  (virConnectPtr conn);
-int testGetVersion(virConnectPtr conn,
-                  unsigned long *hvVer);
-int testNodeGetInfo(virConnectPtr conn,
-                   virNodeInfoPtr info);
-int testNumOfDomains(virConnectPtr conn);
-int testListDomains(virConnectPtr conn,
-                   int *ids,
-                   int maxids);
-char *testGetOSType(virDomainPtr dom);
-virDomainPtr
-testDomainCreateLinux(virConnectPtr conn, const char *xmlDesc,
-                     unsigned int flags ATTRIBUTE_UNUSED);
-virDomainPtr testLookupDomainByID(virConnectPtr conn,
-                                 int id);
-virDomainPtr testLookupDomainByUUID(virConnectPtr conn,
-                                   const unsigned char *uuid);
-virDomainPtr testLookupDomainByName(virConnectPtr conn,
-                                   const char *name);
-int testDestroyDomain(virDomainPtr domain);
-int testResumeDomain(virDomainPtr domain);
-int testPauseDomain(virDomainPtr domain);
-int testShutdownDomain (virDomainPtr domain);
-int testRebootDomain (virDomainPtr domain,
-                     virDomainRestart action);
-int testGetDomainInfo(virDomainPtr domain,
-                     virDomainInfoPtr info);
-unsigned long testGetMaxMemory(virDomainPtr domain);
-int testSetMaxMemory(virDomainPtr domain,
-                    unsigned long memory);
-int testSetMemory(virDomainPtr domain,
-                 unsigned long memory);
-int testSetVcpus(virDomainPtr domain,
-                unsigned int nrCpus);
-char * testDomainDumpXML(virDomainPtr domain, int flags);
+    void testRegister(void);
 
 #ifdef __cplusplus
 }
 #endif
-#endif                          /* __VIR_TEST_INTERNAL_H__ */
+#endif /* __VIR_TEST_INTERNAL_H__ */
+
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */