libvirt/src/test.c
2006-06-06 03:32:51 +00:00

351 lines
8.0 KiB
C

/*
* test.c: A "mock" hypervisor for use by application unit tests
*
* Copyright (C) 2006 Red Hat, Inc.
*
* See COPYING.LIB for the License of this software
*
* Daniel Berrange <berrange@redhat.com>
*/
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <libxml/uri.h>
#include "internal.h"
#include "test.h"
static virDriver testDriver = {
"Test",
NULL, /* init */
testOpen, /* open */
testClose, /* close */
NULL, /* type */
testGetVersion, /* version */
testNodeGetInfo, /* nodeGetInfo */
testListDomains, /* listDomains */
testNumOfDomains, /* numOfDomains */
NULL, /* domainCreateLinux */
testLookupDomainByID, /* domainLookupByID */
testLookupDomainByUUID, /* domainLookupByUUID */
testLookupDomainByName, /* domainLookupByName */
testPauseDomain, /* domainSuspend */
testResumeDomain, /* domainResume */
NULL, /* domainShutdown */
NULL, /* domainReboot */
testDestroyDomain, /* domainDestroy */
NULL, /* domainFree */
NULL, /* domainGetName */
NULL, /* domainGetID */
NULL, /* domainGetUUID */
NULL, /* domainGetOSType */
NULL, /* domainGetMaxMemory */
testSetMaxMemory, /* domainSetMaxMemory */
NULL, /* domainSetMemory */
testGetDomainInfo, /* domainGetInfo */
NULL, /* domainSave */
NULL /* domainRestore */
};
typedef struct _testDev {
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;
virDomainRestart onRestart;
int numDevices;
testDev devices[MAX_DEVICES];
} testDom;
#define MAX_DOMAINS 20
typedef struct _testCon {
int active;
int numDomains;
testDom domains[MAX_DOMAINS];
} testCon;
#define MAX_CONNECTIONS 5
typedef struct _testNode {
int numConnections;
testCon connections[MAX_CONNECTIONS];
} testNode;
/* XXX, how about we stuff this in a SHM
segment so multiple apps can run tests
against the mock hypervisor concurrently.
Would need a pthread process shared mutex
too probably */
static testNode *node = NULL;
static virNodeInfo nodeInfo = {
"i86",
1024*1024*3, /* 3 GB */
16,
1400,
2,
2,
2,
2,
};
static void
testError(virConnectPtr con,
virDomainPtr dom,
virErrorNumber error,
const char *info)
{
const char *errmsg;
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);
}
/**
* testRegister:
*
* Registers the test driver
*/
void testRegister(void)
{
virRegisterDriver(&testDriver);
}
int testOpen(virConnectPtr conn,
const char *name,
int flags)
{
xmlURIPtr uri;
int i, j;
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 ||
strcmp(uri->path, "/default")) {
xmlFreeURI(uri);
return -1;
}
xmlFreeURI(uri);
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) {
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)
{
testCon *con = &node->connections[conn->handle];
con->active = 0;
conn->handle = -1;
memset(con, 0, sizeof(testCon));
return 0;
}
int testGetVersion(virConnectPtr conn,
unsigned long *hvVer)
{
*hvVer = 1;
return 0;
}
int testNodeGetInfo(virConnectPtr conn,
virNodeInfoPtr info)
{
memcpy(info, &nodeInfo, sizeof(nodeInfo));
return 0;
}
int testNumOfDomains(virConnectPtr conn)
{
testCon *con = &node->connections[conn->handle];
return con->numDomains;
}
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;
}
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);
}
dom->handle = id;
}
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);
}
dom->handle = id;
}
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;
}
}
return n;
}
int testDestroyDomain (virDomainPtr domain)
{
testCon *con = &node->connections[domain->conn->handle];
con->domains[domain->handle].active = 0;
return 0;
}
int testResumeDomain (virDomainPtr domain)
{
testCon *con = &node->connections[domain->conn->handle];
con->domains[domain->handle].info.state = VIR_DOMAIN_RUNNING;
return 0;
}
int testPauseDomain (virDomainPtr domain)
{
testCon *con = &node->connections[domain->conn->handle];
con->domains[domain->handle].info.state = VIR_DOMAIN_PAUSED;
return 0;
}
int testGetDomainInfo (virDomainPtr domain,
virDomainInfoPtr info)
{
testCon *con = &node->connections[domain->conn->handle];
struct timeval tv;
if (gettimeofday(&tv, NULL) < 0) {
testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot get timeofday");
return -1;
}
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;
}
int testSetMaxMemory (virDomainPtr domain,
unsigned long memory)
{
testCon *con = &node->connections[domain->conn->handle];
con->domains[domain->handle].info.maxMem = memory;
return 0;
}