mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-27 11:01:19 +00:00
Hook up more test driver methods. Allow HV config to be loaded from extenral XML definition
This commit is contained in:
parent
64d25e8de5
commit
5c2831b30b
@ -1,3 +1,11 @@
|
|||||||
|
Wed Aug 16 11:38:02 EDT 2006 Daniel Berrange <berrange@redhat.com>
|
||||||
|
|
||||||
|
* src/test.c, src/test.h: Allow a hypervisor config to be
|
||||||
|
loaded from an external XML file. Implement drivers for
|
||||||
|
setMemory, setMaxMemory, createLinux, dumpXML, setVcpus.
|
||||||
|
* docs/testnode.xml, docs/testfc4.xml, docs/testfv0.xml:
|
||||||
|
Example config for using with test driver
|
||||||
|
|
||||||
Wed Aug 16 11:36:21 EDT 2006 Daniel Berrange <berrange@redhat.com>
|
Wed Aug 16 11:36:21 EDT 2006 Daniel Berrange <berrange@redhat.com>
|
||||||
|
|
||||||
* src/xend_internal.c, src/xml.c, src/xml.h: Refactored the
|
* src/xend_internal.c, src/xml.c, src/xml.h: Refactored the
|
||||||
|
25
docs/testdomfc4.xml
Normal file
25
docs/testdomfc4.xml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<domain type='test'>
|
||||||
|
<name>fc4</name>
|
||||||
|
<uuid>EF86180145B911CB88E3AFBFE5370493</uuid>
|
||||||
|
<os>
|
||||||
|
<type>linux</type>
|
||||||
|
<kernel>/boot/vmlinuz-2.6.15-1.43_FC5guest</kernel>
|
||||||
|
<initrd>/boot/initrd-2.6.15-1.43_FC5guest.img</initrd>
|
||||||
|
<root>/dev/sda1</root>
|
||||||
|
<cmdline> ro selinux=0 3</cmdline>
|
||||||
|
</os>
|
||||||
|
<memory>131072</memory>
|
||||||
|
<vcpu>1</vcpu>
|
||||||
|
<devices>
|
||||||
|
<disk type='file'>
|
||||||
|
<source file='/u/fc4.img'/>
|
||||||
|
<target dev='sda1'/>
|
||||||
|
</disk>
|
||||||
|
<interface type='bridge'>
|
||||||
|
<source bridge='xenbr0'/>
|
||||||
|
<mac address='aa:00:00:00:00:11'/>
|
||||||
|
<script path='/etc/xen/scripts/vif-bridge'/>
|
||||||
|
</interface>
|
||||||
|
<console tty='/dev/pts/5'/>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
42
docs/testdomfv0.xml
Normal file
42
docs/testdomfv0.xml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<domain type='test'>
|
||||||
|
<name>fv0</name>
|
||||||
|
<uuid>4dea22b31d52d8f32516782e98ab3fa0</uuid>
|
||||||
|
<os>
|
||||||
|
<type>hvm</type>
|
||||||
|
<loader>/usr/lib/xen/boot/hvmloader</loader>
|
||||||
|
<boot dev='hd'/>
|
||||||
|
</os>
|
||||||
|
<memory>524288</memory>
|
||||||
|
<maxMemory>1524288</maxMemory>
|
||||||
|
<vcpu>4</vcpu>
|
||||||
|
<on_poweroff>destroy</on_poweroff>
|
||||||
|
<on_reboot>restart</on_reboot>
|
||||||
|
<on_crash>restart</on_crash>
|
||||||
|
<features>
|
||||||
|
<pae/>
|
||||||
|
<acpi/>
|
||||||
|
<apic/>
|
||||||
|
</features>
|
||||||
|
<devices>
|
||||||
|
<emulator>/usr/lib/xen/bin/qemu-dm</emulator>
|
||||||
|
<interface type='bridge'>
|
||||||
|
<source bridge='xenbr0'/>
|
||||||
|
<mac address='00:16:3e:5d:c7:9e'/>
|
||||||
|
<script path='vif-bridge'/>
|
||||||
|
</interface>
|
||||||
|
<disk type='file'>
|
||||||
|
<source file='/root/fv0'/>
|
||||||
|
<target dev='hda'/>
|
||||||
|
</disk>
|
||||||
|
<disk type='file' device='cdrom'>
|
||||||
|
<source file='/root/fc5-x86_64-boot.iso'/>
|
||||||
|
<target dev='hdc'/>
|
||||||
|
<readonly/>
|
||||||
|
</disk>
|
||||||
|
<disk type='file' device='floppy'>
|
||||||
|
<source file='/root/fd.img'/>
|
||||||
|
<target dev='fda'/>
|
||||||
|
</disk>
|
||||||
|
<graphics type='vnc' port='5904'/>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
23
docs/testnode.xml
Normal file
23
docs/testnode.xml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<node>
|
||||||
|
<!-- This file gives an example config for the mock 'test' backend
|
||||||
|
driver to libvirt. This is intended to allow relible unit testing
|
||||||
|
of applications using libvirt. To use this with virsh, run something
|
||||||
|
like:
|
||||||
|
|
||||||
|
virsh -connect test:////path/to/this/dir/testnode.xml nodeinfo
|
||||||
|
|
||||||
|
-->
|
||||||
|
<domain file="testdomfv0.xml"/>
|
||||||
|
<domain file="testdomfc4.xml"/>
|
||||||
|
|
||||||
|
<cpu>
|
||||||
|
<mhz>6000</mhz>
|
||||||
|
<model>i986</model>
|
||||||
|
<active>50</active>
|
||||||
|
<nodes>4</nodes>
|
||||||
|
<sockets>4</sockets>
|
||||||
|
<cores>4</cores>
|
||||||
|
<threads>2</threads>
|
||||||
|
</cpu>
|
||||||
|
<memory>137438953472</memory>
|
||||||
|
</node>
|
816
src/test.c
816
src/test.c
@ -11,10 +11,16 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <libxml/parser.h>
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include <libxml/xpath.h>
|
||||||
#include <libxml/uri.h>
|
#include <libxml/uri.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
#include "xml.h"
|
||||||
|
|
||||||
static virDriver testDriver = {
|
static virDriver testDriver = {
|
||||||
VIR_DRV_TEST,
|
VIR_DRV_TEST,
|
||||||
@ -28,7 +34,7 @@ static virDriver testDriver = {
|
|||||||
testNodeGetInfo, /* nodeGetInfo */
|
testNodeGetInfo, /* nodeGetInfo */
|
||||||
testListDomains, /* listDomains */
|
testListDomains, /* listDomains */
|
||||||
testNumOfDomains, /* numOfDomains */
|
testNumOfDomains, /* numOfDomains */
|
||||||
NULL, /* domainCreateLinux */
|
testDomainCreateLinux, /* domainCreateLinux */
|
||||||
testLookupDomainByID, /* domainLookupByID */
|
testLookupDomainByID, /* domainLookupByID */
|
||||||
testLookupDomainByUUID, /* domainLookupByUUID */
|
testLookupDomainByUUID, /* domainLookupByUUID */
|
||||||
testLookupDomainByName, /* domainLookupByName */
|
testLookupDomainByName, /* domainLookupByName */
|
||||||
@ -42,16 +48,16 @@ static virDriver testDriver = {
|
|||||||
NULL, /* domainGetID */
|
NULL, /* domainGetID */
|
||||||
NULL, /* domainGetUUID */
|
NULL, /* domainGetUUID */
|
||||||
NULL, /* domainGetOSType */
|
NULL, /* domainGetOSType */
|
||||||
NULL, /* domainGetMaxMemory */
|
testGetMaxMemory, /* domainGetMaxMemory */
|
||||||
testSetMaxMemory, /* domainSetMaxMemory */
|
testSetMaxMemory, /* domainSetMaxMemory */
|
||||||
NULL, /* domainSetMemory */
|
testSetMemory, /* domainSetMemory */
|
||||||
testGetDomainInfo, /* domainGetInfo */
|
testGetDomainInfo, /* domainGetInfo */
|
||||||
NULL, /* domainSave */
|
NULL, /* domainSave */
|
||||||
NULL, /* domainRestore */
|
NULL, /* domainRestore */
|
||||||
NULL, /* domainSetVcpus */
|
testSetVcpus, /* domainSetVcpus */
|
||||||
NULL, /* domainPinVcpu */
|
NULL, /* domainPinVcpu */
|
||||||
NULL, /* domainGetVcpus */
|
NULL, /* domainGetVcpus */
|
||||||
NULL, /* domainDumpXML */
|
testDomainDumpXML, /* domainDumpXML */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Amount of time it takes to shutdown */
|
/* Amount of time it takes to shutdown */
|
||||||
@ -71,7 +77,10 @@ typedef struct _testDom {
|
|||||||
virDomainKernel kernel;
|
virDomainKernel kernel;
|
||||||
virDomainInfo info;
|
virDomainInfo info;
|
||||||
time_t shutdownStartedAt;
|
time_t shutdownStartedAt;
|
||||||
virDomainRestart onRestart;
|
virDomainRestart onRestart; /* What to do at end of current shutdown procedure */
|
||||||
|
virDomainRestart onReboot;
|
||||||
|
virDomainRestart onPoweroff;
|
||||||
|
virDomainRestart onCrash;
|
||||||
int numDevices;
|
int numDevices;
|
||||||
testDev devices[MAX_DEVICES];
|
testDev devices[MAX_DEVICES];
|
||||||
} testDom;
|
} testDom;
|
||||||
@ -80,6 +89,7 @@ typedef struct _testDom {
|
|||||||
|
|
||||||
typedef struct _testCon {
|
typedef struct _testCon {
|
||||||
int active;
|
int active;
|
||||||
|
virNodeInfo nodeInfo;
|
||||||
int numDomains;
|
int numDomains;
|
||||||
testDom domains[MAX_DOMAINS];
|
testDom domains[MAX_DOMAINS];
|
||||||
} testCon;
|
} testCon;
|
||||||
@ -98,8 +108,8 @@ typedef struct _testNode {
|
|||||||
too probably */
|
too probably */
|
||||||
static testNode *node = NULL;
|
static testNode *node = NULL;
|
||||||
|
|
||||||
static virNodeInfo nodeInfo = {
|
static const virNodeInfo defaultNodeInfo = {
|
||||||
"i86",
|
"i686",
|
||||||
1024*1024*3, /* 3 GB */
|
1024*1024*3, /* 3 GB */
|
||||||
16,
|
16,
|
||||||
1400,
|
1400,
|
||||||
@ -125,6 +135,33 @@ testError(virConnectPtr con,
|
|||||||
errmsg, info, NULL, 0, 0, errmsg, info, 0);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* testRegister:
|
* testRegister:
|
||||||
@ -136,13 +173,452 @@ 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, "cannot get timeofday");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
root = xmlDocGetRootElement(xml);
|
||||||
|
if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "domain"))) {
|
||||||
|
testError(conn, NULL, VIR_ERR_INTERNAL_ERROR, "malformed root element");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctxt = xmlXPathNewContext(xml);
|
||||||
|
if (ctxt == NULL) {
|
||||||
|
testError(conn, NULL, VIR_ERR_INTERNAL_ERROR, "cannot create 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, "missing name element on domain");
|
||||||
|
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_INTERNAL_ERROR, "missing uuid element on domain");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
dst_uuid = (char *) &rawuuid[0];
|
||||||
|
if (!(virParseUUID((char **)&dst_uuid, (const char *)obj->stringval))) {
|
||||||
|
testError(conn, NULL, VIR_ERR_INTERNAL_ERROR, "malformed uuid data in domain");
|
||||||
|
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_INTERNAL_ERROR, "missing memory element on domain");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
memory = strtoll((const char*)obj->stringval, &conv, 10);
|
||||||
|
if (conv == (const char*)obj->stringval) {
|
||||||
|
testError(conn, NULL, VIR_ERR_INTERNAL_ERROR, "malformed memory value for domain");
|
||||||
|
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_INTERNAL_ERROR, "malformed vcpus value for domain");
|
||||||
|
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_INTERNAL_ERROR, "malformed on_reboot value for domain");
|
||||||
|
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_INTERNAL_ERROR, "malformed on_poweroff value for domain");
|
||||||
|
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_INTERNAL_ERROR, "malformed on_crash value for domain");
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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_INTERNAL_ERROR, "cannot parse domain definition");
|
||||||
|
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, "cannot load domain definition");
|
||||||
|
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, "cannot parse domain definition");
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
ret = testLoadDomain(conn, domid, xml);
|
||||||
|
|
||||||
|
xmlFreeDoc(xml);
|
||||||
|
|
||||||
|
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, "cannot get timeofday");
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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, "cannot load host definition");
|
||||||
|
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, "cannot parse host definition");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
|
||||||
|
root = xmlDocGetRootElement(xml);
|
||||||
|
if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "node"))) {
|
||||||
|
testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, "malformed root element");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctxt = xmlXPathNewContext(xml);
|
||||||
|
if (ctxt == NULL) {
|
||||||
|
testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot create 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_INTERNAL_ERROR, "malformed nodes value for node cpu");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
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_INTERNAL_ERROR, "malformed sockets value for node cpu");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
xmlXPathFreeObject(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_INTERNAL_ERROR, "malformed cores value for node cpu");
|
||||||
|
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_INTERNAL_ERROR, "malformed threads value for node cpu");
|
||||||
|
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_INTERNAL_ERROR, "malformed active value for node 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_INTERNAL_ERROR, "malformed threads value for node cpu");
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_INTERNAL_ERROR, "malformed memory value for node");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
xmlXPathFreeObject(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = xmlXPathEval(BAD_CAST "/node/domain", ctxt);
|
||||||
|
if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
|
||||||
|
(obj->nodesetval == NULL)) {
|
||||||
|
testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot extract domain list");
|
||||||
|
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);
|
||||||
|
free(domFile);
|
||||||
|
if (!absFile) {
|
||||||
|
testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot resolve filename");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (testLoadDomainFromFile(conn, i, absFile) != 0) {
|
||||||
|
free(absFile);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
free(absFile);
|
||||||
|
node->connections[connid].numDomains++;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlXPathFreeObject(obj);
|
||||||
|
xmlFreeDoc(xml);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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_INTERNAL_ERROR, "cannot allocate memory");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0 ; i < MAX_CONNECTIONS ; i++) {
|
||||||
|
if (!node->connections[i].active) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int testOpen(virConnectPtr conn,
|
int testOpen(virConnectPtr conn,
|
||||||
const char *name,
|
const char *name,
|
||||||
int flags)
|
int flags)
|
||||||
{
|
{
|
||||||
xmlURIPtr uri;
|
xmlURIPtr uri;
|
||||||
int i, j;
|
int ret, connid;
|
||||||
|
|
||||||
if (!name) {
|
if (!name) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -157,53 +633,29 @@ int testOpen(virConnectPtr conn,
|
|||||||
|
|
||||||
if (!uri->scheme ||
|
if (!uri->scheme ||
|
||||||
strcmp(uri->scheme, "test") ||
|
strcmp(uri->scheme, "test") ||
|
||||||
!uri->path ||
|
!uri->path) {
|
||||||
strcmp(uri->path, "/default")) {
|
|
||||||
xmlFreeURI(uri);
|
xmlFreeURI(uri);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
xmlFreeURI(uri);
|
||||||
|
|
||||||
if (node == NULL) {
|
return (ret);
|
||||||
node = calloc(1, sizeof(testNode));
|
|
||||||
if (!node) {
|
|
||||||
testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot allocate memory");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0 ; i < MAX_CONNECTIONS ; i++) {
|
|
||||||
if (!node->connections[i].active) {
|
|
||||||
struct timeval tv;
|
|
||||||
|
|
||||||
if (gettimeofday(&tv, NULL) < 0) {
|
|
||||||
testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot get timeofday");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
conn->handle = i;
|
|
||||||
node->connections[i].active = 1;
|
|
||||||
|
|
||||||
node->connections[i].numDomains = 1;
|
|
||||||
node->connections[i].domains[0].active = 1;
|
|
||||||
strcpy(node->connections[i].domains[0].name, "Domain-0");
|
|
||||||
for (j = 0 ; j < 16 ; j++) {
|
|
||||||
node->connections[i].domains[0].uuid[j] = (j * 75)%255;
|
|
||||||
}
|
|
||||||
node->connections[i].domains[0].info.maxMem = 8192 * 1024;
|
|
||||||
node->connections[i].domains[0].info.memory = 2048 * 1024;
|
|
||||||
node->connections[i].domains[0].info.state = VIR_DOMAIN_RUNNING;
|
|
||||||
node->connections[i].domains[0].info.nrVirtCpu = 2;
|
|
||||||
node->connections[i].domains[0].info.cpuTime = ((tv.tv_sec * 1000ll * 1000ll * 1000ll) + (tv.tv_usec * 1000ll));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, "too make connections");
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int testClose(virConnectPtr conn)
|
int testClose(virConnectPtr conn)
|
||||||
@ -218,14 +670,15 @@ int testClose(virConnectPtr conn)
|
|||||||
int testGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
|
int testGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||||
unsigned long *hvVer)
|
unsigned long *hvVer)
|
||||||
{
|
{
|
||||||
*hvVer = 1;
|
*hvVer = 2;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int testNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED,
|
int testNodeGetInfo(virConnectPtr conn,
|
||||||
virNodeInfoPtr info)
|
virNodeInfoPtr info)
|
||||||
{
|
{
|
||||||
memcpy(info, &nodeInfo, sizeof(nodeInfo));
|
testCon *con = &node->connections[conn->handle];
|
||||||
|
memcpy(info, &con->nodeInfo, sizeof(virNodeInfo));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,14 +688,58 @@ int testNumOfDomains(virConnectPtr conn)
|
|||||||
return con->numDomains;
|
return con->numDomains;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virDomainPtr
|
||||||
|
testDomainCreateLinux(virConnectPtr conn, const char *xmlDesc,
|
||||||
|
unsigned int flags ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
testCon *con;
|
||||||
|
int 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_READ_ONLY, __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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, "too many domains");
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
virDomainPtr testLookupDomainByID(virConnectPtr conn,
|
virDomainPtr testLookupDomainByID(virConnectPtr conn,
|
||||||
int id)
|
int id)
|
||||||
{
|
{
|
||||||
testCon *con = &node->connections[conn->handle];
|
testCon *con = &node->connections[conn->handle];
|
||||||
virDomainPtr dom;
|
virDomainPtr dom;
|
||||||
|
|
||||||
if (!con->domains[id].active) {
|
if (!con->domains[id].active) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
dom = virGetDomain(conn, con->domains[id].name, con->domains[id].uuid);
|
dom = virGetDomain(conn, con->domains[id].name, con->domains[id].uuid);
|
||||||
if (dom == NULL) {
|
if (dom == NULL) {
|
||||||
testError(conn, NULL, VIR_ERR_NO_MEMORY, "Allocating domain");
|
testError(conn, NULL, VIR_ERR_NO_MEMORY, "Allocating domain");
|
||||||
@ -317,23 +814,56 @@ int testListDomains (virConnectPtr conn,
|
|||||||
|
|
||||||
int testDestroyDomain (virDomainPtr domain)
|
int testDestroyDomain (virDomainPtr domain)
|
||||||
{
|
{
|
||||||
testCon *con = &node->connections[domain->conn->handle];
|
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_READ_ONLY, __FUNCTION__);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
con = &node->connections[domain->conn->handle];
|
||||||
con->domains[domain->handle].active = 0;
|
con->domains[domain->handle].active = 0;
|
||||||
return 0;
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int testResumeDomain (virDomainPtr domain)
|
int testResumeDomain (virDomainPtr domain)
|
||||||
{
|
{
|
||||||
testCon *con = &node->connections[domain->conn->handle];
|
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_READ_ONLY, __FUNCTION__);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
con = &node->connections[domain->conn->handle];
|
||||||
con->domains[domain->handle].info.state = VIR_DOMAIN_RUNNING;
|
con->domains[domain->handle].info.state = VIR_DOMAIN_RUNNING;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int testPauseDomain (virDomainPtr domain)
|
int testPauseDomain (virDomainPtr domain)
|
||||||
{
|
{
|
||||||
testCon *con = &node->connections[domain->conn->handle];
|
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_READ_ONLY, __FUNCTION__);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
con = &node->connections[domain->conn->handle];
|
||||||
con->domains[domain->handle].info.state = VIR_DOMAIN_PAUSED;
|
con->domains[domain->handle].info.state = VIR_DOMAIN_PAUSED;
|
||||||
return 0;
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We don't do an immediate shutdown. We basically pretend that
|
/* We don't do an immediate shutdown. We basically pretend that
|
||||||
@ -342,27 +872,51 @@ int testPauseDomain (virDomainPtr domain)
|
|||||||
will check to see if shutdown ought to be marked complete. */
|
will check to see if shutdown ought to be marked complete. */
|
||||||
int testShutdownDomain (virDomainPtr domain)
|
int testShutdownDomain (virDomainPtr domain)
|
||||||
{
|
{
|
||||||
testCon *con = &node->connections[domain->conn->handle];
|
testCon *con;
|
||||||
struct timeval tv;
|
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_READ_ONLY, __FUNCTION__);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
con = &node->connections[domain->conn->handle];
|
||||||
|
|
||||||
if (gettimeofday(&tv, NULL) < 0) {
|
if (gettimeofday(&tv, NULL) < 0) {
|
||||||
testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot get timeofday");
|
testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot get timeofday");
|
||||||
return -1;
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
con->domains[domain->handle].info.state = VIR_DOMAIN_SHUTDOWN;
|
con->domains[domain->handle].info.state = VIR_DOMAIN_SHUTDOWN;
|
||||||
con->domains[domain->handle].onRestart = VIR_DOMAIN_DESTROY;
|
con->domains[domain->handle].onRestart = VIR_DOMAIN_DESTROY;
|
||||||
con->domains[domain->handle].shutdownStartedAt = tv.tv_sec;
|
con->domains[domain->handle].shutdownStartedAt = tv.tv_sec;
|
||||||
return 0;
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Similar behaviour as shutdown */
|
/* Similar behaviour as shutdown */
|
||||||
int testRebootDomain (virDomainPtr domain, virDomainRestart action)
|
int testRebootDomain (virDomainPtr domain, virDomainRestart action)
|
||||||
{
|
{
|
||||||
testCon *con = &node->connections[domain->conn->handle];
|
testCon *con;
|
||||||
struct timeval tv;
|
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_READ_ONLY, __FUNCTION__);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
con = &node->connections[domain->conn->handle];
|
||||||
|
|
||||||
if (gettimeofday(&tv, NULL) < 0) {
|
if (gettimeofday(&tv, NULL) < 0) {
|
||||||
testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot get timeofday");
|
testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot get timeofday");
|
||||||
return -1;
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!action)
|
if (!action)
|
||||||
@ -371,17 +925,25 @@ int testRebootDomain (virDomainPtr domain, virDomainRestart action)
|
|||||||
con->domains[domain->handle].info.state = VIR_DOMAIN_SHUTDOWN;
|
con->domains[domain->handle].info.state = VIR_DOMAIN_SHUTDOWN;
|
||||||
con->domains[domain->handle].onRestart = action;
|
con->domains[domain->handle].onRestart = action;
|
||||||
con->domains[domain->handle].shutdownStartedAt = tv.tv_sec;
|
con->domains[domain->handle].shutdownStartedAt = tv.tv_sec;
|
||||||
return 0;
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int testGetDomainInfo (virDomainPtr domain,
|
int testGetDomainInfo (virDomainPtr domain,
|
||||||
virDomainInfoPtr info)
|
virDomainInfoPtr info)
|
||||||
{
|
{
|
||||||
testCon *con = &node->connections[domain->conn->handle];
|
|
||||||
struct timeval tv;
|
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) {
|
if (gettimeofday(&tv, NULL) < 0) {
|
||||||
testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot get timeofday");
|
testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot get timeofday");
|
||||||
return -1;
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check to see if there is an in-progresss shutdown/reboot that
|
/* Check to see if there is an in-progresss shutdown/reboot that
|
||||||
@ -419,13 +981,129 @@ int testGetDomainInfo (virDomainPtr domain,
|
|||||||
con->domains[domain->handle].info.cpuTime = ((tv.tv_sec * 1000ll * 1000ll * 1000ll) + (tv.tv_usec * 1000ll));
|
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));
|
memcpy(info, &con->domains[domain->handle].info, sizeof(virDomainInfo));
|
||||||
return 0;
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
int testSetMaxMemory (virDomainPtr domain,
|
int testSetMaxMemory (virDomainPtr domain,
|
||||||
unsigned long memory)
|
unsigned long memory)
|
||||||
{
|
{
|
||||||
testCon *con = &node->connections[domain->conn->handle];
|
testCon *con;
|
||||||
con->domains[domain->handle].info.maxMem = memory;
|
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
|
||||||
return 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_READ_ONLY, __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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_READ_ONLY, __FUNCTION__);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
con = &node->connections[domain->conn->handle];
|
||||||
|
|
||||||
|
if (memory > con->domains[domain->handle].info.maxMem) {
|
||||||
|
testError(domain->conn, domain, VIR_ERR_INVALID_ARG, "memory over maximum limit");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
con->domains[domain->handle].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_READ_ONLY, __FUNCTION__);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
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, "too many virtual cpus");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
con->domains[domain->handle].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;
|
||||||
}
|
}
|
||||||
|
11
src/test.h
11
src/test.h
@ -30,6 +30,9 @@ int testNumOfDomains(virConnectPtr conn);
|
|||||||
int testListDomains(virConnectPtr conn,
|
int testListDomains(virConnectPtr conn,
|
||||||
int *ids,
|
int *ids,
|
||||||
int maxids);
|
int maxids);
|
||||||
|
virDomainPtr
|
||||||
|
testDomainCreateLinux(virConnectPtr conn, const char *xmlDesc,
|
||||||
|
unsigned int flags ATTRIBUTE_UNUSED);
|
||||||
virDomainPtr testLookupDomainByID(virConnectPtr conn,
|
virDomainPtr testLookupDomainByID(virConnectPtr conn,
|
||||||
int id);
|
int id);
|
||||||
virDomainPtr testLookupDomainByUUID(virConnectPtr conn,
|
virDomainPtr testLookupDomainByUUID(virConnectPtr conn,
|
||||||
@ -44,10 +47,14 @@ int testRebootDomain (virDomainPtr domain,
|
|||||||
virDomainRestart action);
|
virDomainRestart action);
|
||||||
int testGetDomainInfo(virDomainPtr domain,
|
int testGetDomainInfo(virDomainPtr domain,
|
||||||
virDomainInfoPtr info);
|
virDomainInfoPtr info);
|
||||||
int testGetDomainID(virDomainPtr domain);
|
unsigned long testGetMaxMemory(virDomainPtr domain);
|
||||||
const char*testGetDomainName(virDomainPtr domain);
|
|
||||||
int testSetMaxMemory(virDomainPtr domain,
|
int testSetMaxMemory(virDomainPtr domain,
|
||||||
unsigned long memory);
|
unsigned long memory);
|
||||||
|
int testSetMemory(virDomainPtr domain,
|
||||||
|
unsigned long memory);
|
||||||
|
int testSetVcpus(virDomainPtr domain,
|
||||||
|
unsigned int nrCpus);
|
||||||
|
char * testDomainDumpXML(virDomainPtr domain, int flags);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user