2006-06-06 03:32:51 +00:00
|
|
|
/*
|
|
|
|
* test.c: A "mock" hypervisor for use by application unit tests
|
|
|
|
*
|
2008-01-30 19:52:16 +00:00
|
|
|
* Copyright (C) 2006-2008 Red Hat, Inc.
|
2007-01-18 21:08:21 +00:00
|
|
|
* Copyright (C) 2006 Daniel P. Berrange
|
2006-06-06 03:32:51 +00:00
|
|
|
*
|
2007-01-18 21:08:21 +00:00
|
|
|
* 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
|
2006-06-06 03:32:51 +00:00
|
|
|
*
|
|
|
|
* Daniel Berrange <berrange@redhat.com>
|
|
|
|
*/
|
|
|
|
|
2008-01-29 18:15:54 +00:00
|
|
|
#include <config.h>
|
2007-11-26 11:50:16 +00:00
|
|
|
|
2007-03-15 07:43:16 +00:00
|
|
|
#ifdef WITH_TEST
|
2007-06-26 11:42:46 +00:00
|
|
|
|
2006-06-06 03:32:51 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/time.h>
|
2006-08-16 16:36:39 +00:00
|
|
|
#include <libxml/parser.h>
|
|
|
|
#include <libxml/tree.h>
|
|
|
|
#include <libxml/xpath.h>
|
2006-06-06 03:32:51 +00:00
|
|
|
#include <libxml/uri.h>
|
2006-08-16 16:36:39 +00:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
2007-12-07 14:45:39 +00:00
|
|
|
#include <sys/stat.h>
|
|
|
|
|
2008-01-05 16:06:36 +00:00
|
|
|
#include "socketcompat.h"
|
2006-06-06 03:32:51 +00:00
|
|
|
|
|
|
|
#include "internal.h"
|
|
|
|
#include "test.h"
|
2006-08-16 16:36:39 +00:00
|
|
|
#include "xml.h"
|
2007-06-26 22:33:22 +00:00
|
|
|
#include "buf.h"
|
Use safewrite in place of write, in many cases.
Also add "make syntax-check" rules to ensure no new uses sneak in.
There are many uses of write like this:
if (write (fd, xml, towrite) != towrite)
return -1;
The problem is that the syscall can succeed, yet write less than
the requested number of bytes, so the caller should retry
rather than simply failing.
This patch changes most of them to use util.c's safewrite wrapper,
which encapsulates the process. Also, there were a few cases in
which the retry loop was open-coded, and I replaced those, too.
* Makefile.maint (sc_avoid_write): New rule, to avoid recurrence.
* .x-sc_avoid_write: New file. Record two legitimate exemptions.
* qemud/qemud.c (sig_handler, qemudClientWriteBuf): Use safewrite, not write.
* src/conf.c (__virConfWriteFile): Likewise.
* src/qemu_conf.c (qemudSaveConfig, qemudSaveNetworkConfig): Likewise.
* src/qemu_driver.c (qemudWaitForMonitor, qemudStartVMDaemon)
(qemudVMData, PROC_IP_FORWARD): Likewise.
* proxy/libvirt_proxy.c: Include "util.h".
(proxyWriteClientSocket): Use safewrite.
* src/test.c (testDomainSave, testDomainCoreDump): Likewise.
* src/proxy_internal.c (virProxyWriteClientSocket): Likewise.
* src/virsh.c: Include "util-lib.h".
(vshOutputLogFile): Use safewrite.
* src/console.c: Include "util-lib.h".
(vshRunConsole): Use safewrite.
2008-02-22 15:55:04 +00:00
|
|
|
#include "util.h"
|
2007-08-09 20:19:12 +00:00
|
|
|
#include "uuid.h"
|
2008-02-27 04:35:08 +00:00
|
|
|
#include "capabilities.h"
|
2008-05-29 19:20:22 +00:00
|
|
|
#include "memory.h"
|
2007-04-04 14:19:49 +00:00
|
|
|
|
2007-10-15 14:32:35 +00:00
|
|
|
/* Flags that determine the action to take on a shutdown or crash of a domain
|
|
|
|
*/
|
|
|
|
typedef enum {
|
|
|
|
VIR_DOMAIN_DESTROY = 1, /* destroy the domain */
|
|
|
|
VIR_DOMAIN_RESTART = 2, /* restart the domain */
|
|
|
|
VIR_DOMAIN_PRESERVE= 3, /* keep as is, need manual destroy, for debug */
|
|
|
|
VIR_DOMAIN_RENAME_RESTART= 4/* restart under an new unique name */
|
|
|
|
} virDomainRestart;
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
struct _testDev {
|
2007-01-18 21:08:21 +00:00
|
|
|
char name[20];
|
2007-07-18 10:11:09 +00:00
|
|
|
int mode;
|
2007-07-27 23:23:00 +00:00
|
|
|
};
|
|
|
|
typedef struct _testDev testDev;
|
|
|
|
typedef struct _testDev *testDevPtr;
|
2006-06-06 03:32:51 +00:00
|
|
|
|
|
|
|
#define MAX_DEVICES 10
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
struct _testDom {
|
2007-01-18 21:08:21 +00:00
|
|
|
int active;
|
2007-07-27 23:23:00 +00:00
|
|
|
int config;
|
2007-01-22 16:25:27 +00:00
|
|
|
int id;
|
2007-01-18 21:08:21 +00:00
|
|
|
char name[20];
|
Mon Jan 23 14:36:18 IST 2007 Mark McLoughlin <markmc@redhat.com>
* include/libvirt/libvirt.h.in: add VIR_UUID_BUFLEN and
VIR_UUID_STRING_BUFLEN
* libvirt/proxy/libvirt_proxy.c, libvirt/src/hash.c,
libvirt/src/internal.h, libvirt/src/libvirt.c,
libvirt/src/proxy_internal.c, libvirt/src/test.c,
libvirt/src/virsh.c, libvirt/src/xend_internal.c,
libvirt/src/xm_internal.c, libvirt/src/xml.c,
libvirt/python/libvir.c: use them
2007-01-23 14:39:45 +00:00
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
2007-01-18 21:08:21 +00:00
|
|
|
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];
|
2007-07-27 23:23:00 +00:00
|
|
|
int autostart;
|
|
|
|
unsigned int weight;
|
|
|
|
};
|
|
|
|
typedef struct _testDom testDom;
|
|
|
|
typedef struct _testDom *testDomPtr;
|
|
|
|
|
|
|
|
struct _testNet {
|
|
|
|
int active;
|
|
|
|
int config;
|
|
|
|
int running;
|
|
|
|
char name[20];
|
|
|
|
char bridge[20];
|
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
|
|
|
int forward;
|
|
|
|
char forwardDev[IF_NAMESIZE];
|
|
|
|
char ipAddress[INET_ADDRSTRLEN];
|
|
|
|
char ipNetmask[INET_ADDRSTRLEN];
|
|
|
|
|
|
|
|
char dhcpStart[INET_ADDRSTRLEN];
|
|
|
|
char dhcpEnd[INET_ADDRSTRLEN];
|
|
|
|
|
|
|
|
int autostart;
|
|
|
|
};
|
|
|
|
typedef struct _testNet testNet;
|
|
|
|
typedef struct _testNet *testNetPtr;
|
2006-06-06 03:32:51 +00:00
|
|
|
|
|
|
|
#define MAX_DOMAINS 20
|
2007-07-27 23:23:00 +00:00
|
|
|
#define MAX_NETWORKS 20
|
2008-04-04 07:31:24 +00:00
|
|
|
#define MAX_CPUS 128
|
|
|
|
|
|
|
|
struct _testCell {
|
|
|
|
unsigned long mem;
|
|
|
|
int numCpus;
|
|
|
|
int cpus[MAX_CPUS];
|
|
|
|
};
|
|
|
|
typedef struct _testCell testCell;
|
|
|
|
typedef struct _testCell *testCellPtr;
|
|
|
|
|
|
|
|
#define MAX_CELLS 128
|
2006-06-06 03:32:51 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
struct _testConn {
|
|
|
|
char path[PATH_MAX];
|
|
|
|
int nextDomID;
|
2007-01-18 21:08:21 +00:00
|
|
|
virNodeInfo nodeInfo;
|
|
|
|
int numDomains;
|
|
|
|
testDom domains[MAX_DOMAINS];
|
2007-07-27 23:23:00 +00:00
|
|
|
int numNetworks;
|
|
|
|
testNet networks[MAX_NETWORKS];
|
2008-04-04 07:31:24 +00:00
|
|
|
int numCells;
|
|
|
|
testCell cells[MAX_CELLS];
|
2007-07-27 23:23:00 +00:00
|
|
|
};
|
|
|
|
typedef struct _testConn testConn;
|
|
|
|
typedef struct _testConn *testConnPtr;
|
2006-06-06 03:32:51 +00:00
|
|
|
|
2007-03-15 17:24:56 +00:00
|
|
|
#define TEST_MODEL "i686"
|
2008-02-27 04:35:08 +00:00
|
|
|
#define TEST_MODEL_WORDSIZE 32
|
2007-03-15 17:24:56 +00:00
|
|
|
|
2006-08-16 16:36:39 +00:00
|
|
|
static const virNodeInfo defaultNodeInfo = {
|
2007-03-15 17:24:56 +00:00
|
|
|
TEST_MODEL,
|
2007-01-18 21:08:21 +00:00
|
|
|
1024*1024*3, /* 3 GB */
|
|
|
|
16,
|
|
|
|
1400,
|
|
|
|
2,
|
|
|
|
2,
|
|
|
|
2,
|
|
|
|
2,
|
2006-06-06 03:32:51 +00:00
|
|
|
};
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
#define GET_DOMAIN(dom, ret) \
|
|
|
|
int domidx; \
|
|
|
|
testConnPtr privconn; \
|
|
|
|
testDomPtr privdom; \
|
|
|
|
\
|
|
|
|
privconn = (testConnPtr)dom->conn->privateData; \
|
|
|
|
if ((domidx = getDomainIndex(dom)) < 0) { \
|
|
|
|
testError((dom)->conn, (dom), NULL, VIR_ERR_INVALID_ARG, \
|
|
|
|
__FUNCTION__); \
|
|
|
|
return (ret); \
|
|
|
|
} \
|
|
|
|
privdom = &privconn->domains[domidx];
|
|
|
|
|
|
|
|
#define GET_NETWORK(net, ret) \
|
|
|
|
int netidx; \
|
|
|
|
testConnPtr privconn; \
|
|
|
|
testNetPtr privnet; \
|
|
|
|
\
|
|
|
|
privconn = (testConnPtr)net->conn->privateData; \
|
|
|
|
if ((netidx = getNetworkIndex(net)) < 0) { \
|
|
|
|
testError((net)->conn, NULL, (net), VIR_ERR_INVALID_ARG, \
|
|
|
|
__FUNCTION__); \
|
|
|
|
return (ret); \
|
|
|
|
} \
|
|
|
|
privnet = &privconn->networks[netidx];
|
|
|
|
|
|
|
|
#define GET_CONNECTION(conn, ret) \
|
|
|
|
testConnPtr privconn; \
|
|
|
|
\
|
|
|
|
privconn = (testConnPtr)conn->privateData;
|
|
|
|
|
|
|
|
|
2006-06-06 03:32:51 +00:00
|
|
|
static void
|
|
|
|
testError(virConnectPtr con,
|
2007-01-18 21:08:21 +00:00
|
|
|
virDomainPtr dom,
|
2007-07-27 23:23:00 +00:00
|
|
|
virNetworkPtr net,
|
2007-01-18 21:08:21 +00:00
|
|
|
virErrorNumber error,
|
|
|
|
const char *info)
|
2006-06-06 03:32:51 +00:00
|
|
|
{
|
2007-01-18 21:08:21 +00:00
|
|
|
const char *errmsg;
|
2006-06-06 03:32:51 +00:00
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
if (error == VIR_ERR_OK)
|
|
|
|
return;
|
2006-06-06 03:32:51 +00:00
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
errmsg = __virErrorMsg(error, info);
|
2007-07-27 23:23:00 +00:00
|
|
|
__virRaiseError(con, dom, net, VIR_FROM_TEST, error, VIR_ERR_ERROR,
|
2007-01-18 21:08:21 +00:00
|
|
|
errmsg, info, NULL, 0, 0, errmsg, info, 0);
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
|
|
|
|
2006-08-16 16:36:39 +00:00
|
|
|
static int testRestartStringToFlag(const char *str) {
|
2008-05-14 19:51:24 +00:00
|
|
|
if (STREQ(str, "restart")) {
|
2007-01-18 21:08:21 +00:00
|
|
|
return VIR_DOMAIN_RESTART;
|
2008-05-14 19:51:24 +00:00
|
|
|
} else if (STREQ(str, "destroy")) {
|
2007-01-18 21:08:21 +00:00
|
|
|
return VIR_DOMAIN_DESTROY;
|
2008-05-14 19:51:24 +00:00
|
|
|
} else if (STREQ(str, "preserve")) {
|
2007-01-18 21:08:21 +00:00
|
|
|
return VIR_DOMAIN_PRESERVE;
|
2008-05-14 19:51:24 +00:00
|
|
|
} else if (STREQ(str, "rename-restart")) {
|
2007-01-18 21:08:21 +00:00
|
|
|
return VIR_DOMAIN_RENAME_RESTART;
|
|
|
|
} else {
|
|
|
|
return (0);
|
|
|
|
}
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static const char *testRestartFlagToString(int flag) {
|
2007-01-18 21:08:21 +00:00
|
|
|
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);
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
2006-06-06 03:32:51 +00:00
|
|
|
|
|
|
|
|
2006-08-16 16:36:39 +00:00
|
|
|
static int testLoadDomain(virConnectPtr conn,
|
2007-01-18 21:08:21 +00:00
|
|
|
int domid,
|
|
|
|
xmlDocPtr xml) {
|
|
|
|
xmlNodePtr root = NULL;
|
|
|
|
xmlXPathContextPtr ctxt = NULL;
|
|
|
|
char *name = NULL;
|
2007-08-09 20:19:12 +00:00
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
2007-01-18 21:08:21 +00:00
|
|
|
struct timeval tv;
|
|
|
|
unsigned long memory = 0;
|
|
|
|
unsigned long maxMem = 0;
|
|
|
|
int nrVirtCpu;
|
2007-04-06 15:34:09 +00:00
|
|
|
char *str;
|
|
|
|
int handle = -1, i, ret;
|
|
|
|
long l;
|
2007-01-18 21:08:21 +00:00
|
|
|
virDomainRestart onReboot = VIR_DOMAIN_RESTART;
|
|
|
|
virDomainRestart onPoweroff = VIR_DOMAIN_DESTROY;
|
|
|
|
virDomainRestart onCrash = VIR_DOMAIN_RENAME_RESTART;
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_CONNECTION(conn, -1);
|
2007-01-18 21:08:21 +00:00
|
|
|
|
|
|
|
if (gettimeofday(&tv, NULL) < 0) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("getting time of day"));
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
root = xmlDocGetRootElement(xml);
|
|
|
|
if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "domain"))) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain"));
|
2007-01-18 21:08:21 +00:00
|
|
|
goto error;
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
2007-01-18 21:08:21 +00:00
|
|
|
|
|
|
|
ctxt = xmlXPathNewContext(xml);
|
|
|
|
if (ctxt == NULL) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("creating xpath context"));
|
2007-01-18 21:08:21 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2007-04-06 15:34:09 +00:00
|
|
|
name = virXPathString("string(/domain/name[1])", ctxt);
|
|
|
|
if (name == NULL) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("domain name"));
|
2007-01-18 21:08:21 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2007-04-06 15:34:09 +00:00
|
|
|
str = virXPathString("string(/domain/uuid[1])", ctxt);
|
|
|
|
if (str == NULL) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain uuid"));
|
2007-01-18 21:08:21 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-08-09 20:19:12 +00:00
|
|
|
if (virUUIDParse(str, uuid) < 0) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain uuid"));
|
2007-01-18 21:08:21 +00:00
|
|
|
goto error;
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(str);
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2007-04-06 15:34:09 +00:00
|
|
|
|
|
|
|
ret = virXPathLong("string(/domain/memory[1])", ctxt, &l);
|
|
|
|
if (ret != 0) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain memory"));
|
2007-01-18 21:08:21 +00:00
|
|
|
goto error;
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
2007-04-06 15:34:09 +00:00
|
|
|
maxMem = l;
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2007-04-06 15:34:09 +00:00
|
|
|
ret = virXPathLong("string(/domain/currentMemory[1])", ctxt, &l);
|
|
|
|
if (ret == -1) {
|
2007-01-18 21:08:21 +00:00
|
|
|
memory = maxMem;
|
2007-04-06 15:34:09 +00:00
|
|
|
} else if (ret == -2) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain current memory"));
|
|
|
|
goto error;
|
2007-01-18 21:08:21 +00:00
|
|
|
} else {
|
2007-04-06 15:34:09 +00:00
|
|
|
memory = l;
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
|
|
|
|
2007-04-06 15:34:09 +00:00
|
|
|
ret = virXPathLong("string(/domain/vcpu[1])", ctxt, &l);
|
|
|
|
if (ret == -1) {
|
2007-01-18 21:08:21 +00:00
|
|
|
nrVirtCpu = 1;
|
2007-04-06 15:34:09 +00:00
|
|
|
} else if (ret == -2) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain vcpus"));
|
|
|
|
goto error;
|
2007-01-18 21:08:21 +00:00
|
|
|
} else {
|
2007-04-06 15:34:09 +00:00
|
|
|
nrVirtCpu = l;
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
|
|
|
|
2007-04-06 15:34:09 +00:00
|
|
|
str = virXPathString("string(/domain/on_reboot[1])", ctxt);
|
|
|
|
if (str != NULL) {
|
|
|
|
if (!(onReboot = testRestartStringToFlag(str))) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain reboot behaviour"));
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(str);
|
2007-01-18 21:08:21 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(str);
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
|
|
|
|
2007-04-06 15:34:09 +00:00
|
|
|
str = virXPathString("string(/domain/on_poweroff[1])", ctxt);
|
|
|
|
if (str != NULL) {
|
2007-07-27 23:23:00 +00:00
|
|
|
if (!(onPoweroff = testRestartStringToFlag(str))) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain poweroff behaviour"));
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(str);
|
2007-01-18 21:08:21 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(str);
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
|
|
|
|
2007-04-06 15:34:09 +00:00
|
|
|
str = virXPathString("string(/domain/on_crash[1])", ctxt);
|
|
|
|
if (str != NULL) {
|
2007-07-27 23:23:00 +00:00
|
|
|
if (!(onCrash = testRestartStringToFlag(str))) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain crash behaviour"));
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(str);
|
2007-01-18 21:08:21 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(str);
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
for (i = 0 ; i < MAX_DOMAINS ; i++) {
|
2007-07-27 23:23:00 +00:00
|
|
|
if (!privconn->domains[i].active) {
|
2007-01-18 21:08:21 +00:00
|
|
|
handle = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (handle < 0)
|
2008-01-30 19:57:13 +00:00
|
|
|
goto error;
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
privconn->domains[handle].active = 1;
|
|
|
|
privconn->domains[handle].id = domid;
|
|
|
|
strncpy(privconn->domains[handle].name, name, sizeof(privconn->domains[handle].name)-1);
|
|
|
|
privconn->domains[handle].name[sizeof(privconn->domains[handle].name)-1] = '\0';
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(name);
|
2007-01-18 21:08:21 +00:00
|
|
|
name = NULL;
|
|
|
|
|
|
|
|
if (memory > maxMem)
|
|
|
|
memory = maxMem;
|
|
|
|
|
2007-08-09 20:19:12 +00:00
|
|
|
memmove(privconn->domains[handle].uuid, uuid, VIR_UUID_BUFLEN);
|
2007-07-27 23:23:00 +00:00
|
|
|
privconn->domains[handle].info.maxMem = maxMem;
|
|
|
|
privconn->domains[handle].info.memory = memory;
|
|
|
|
privconn->domains[handle].info.state = domid < 0 ? VIR_DOMAIN_SHUTOFF : VIR_DOMAIN_RUNNING;
|
|
|
|
privconn->domains[handle].info.nrVirtCpu = nrVirtCpu;
|
|
|
|
privconn->domains[handle].info.cpuTime = ((tv.tv_sec * 1000ll * 1000ll * 1000ll) + (tv.tv_usec * 1000ll));
|
|
|
|
privconn->domains[handle].maxVCPUs = nrVirtCpu;
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
privconn->domains[handle].onReboot = onReboot;
|
|
|
|
privconn->domains[handle].onPoweroff = onPoweroff;
|
|
|
|
privconn->domains[handle].onCrash = onCrash;
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2008-01-30 19:50:14 +00:00
|
|
|
xmlXPathFreeContext(ctxt);
|
2007-07-27 23:23:00 +00:00
|
|
|
return (handle);
|
2007-01-18 21:08:21 +00:00
|
|
|
|
|
|
|
error:
|
2008-01-30 19:50:14 +00:00
|
|
|
xmlXPathFreeContext(ctxt);
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(name);
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int testLoadDomainFromDoc(virConnectPtr conn,
|
2007-01-18 21:08:21 +00:00
|
|
|
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))) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain"));
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = testLoadDomain(conn, domid, xml);
|
|
|
|
|
|
|
|
xmlFreeDoc(xml);
|
|
|
|
|
|
|
|
return (ret);
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2006-08-16 16:36:39 +00:00
|
|
|
static int testLoadDomainFromFile(virConnectPtr conn,
|
2007-01-18 21:08:21 +00:00
|
|
|
int domid,
|
2007-07-27 23:23:00 +00:00
|
|
|
const char *filename) {
|
2007-01-18 21:08:21 +00:00
|
|
|
int ret, fd;
|
|
|
|
xmlDocPtr xml;
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
if ((fd = open(filename, O_RDONLY)) < 0) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("load domain definition file"));
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
if (!(xml = xmlReadFd(fd, filename, NULL,
|
2007-01-18 21:08:21 +00:00
|
|
|
XML_PARSE_NOENT | XML_PARSE_NONET |
|
|
|
|
XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain"));
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
ret = testLoadDomain(conn, domid, xml);
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
xmlFreeDoc(xml);
|
2007-07-27 23:23:00 +00:00
|
|
|
close(fd);
|
|
|
|
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int testLoadNetwork(virConnectPtr conn,
|
|
|
|
xmlDocPtr xml) {
|
|
|
|
xmlNodePtr root = NULL;
|
|
|
|
xmlXPathContextPtr ctxt = NULL;
|
|
|
|
char *name = NULL, *bridge = NULL;
|
2007-08-09 20:19:12 +00:00
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
2007-07-27 23:23:00 +00:00
|
|
|
char *str;
|
|
|
|
char *ipaddress = NULL, *ipnetmask = NULL, *dhcpstart = NULL, *dhcpend = NULL;
|
|
|
|
int forward;
|
|
|
|
char *forwardDev = NULL;
|
|
|
|
int handle = -1, i;
|
|
|
|
GET_CONNECTION(conn, -1);
|
|
|
|
|
|
|
|
root = xmlDocGetRootElement(xml);
|
|
|
|
if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "network"))) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("network"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctxt = xmlXPathNewContext(xml);
|
|
|
|
if (ctxt == NULL) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("creating xpath context"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
name = virXPathString("string(/network/name[1])", ctxt);
|
|
|
|
if (name == NULL) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("network name"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
bridge = virXPathString("string(/network/bridge[1]/@name)", ctxt);
|
|
|
|
|
|
|
|
str = virXPathString("string(/network/uuid[1])", ctxt);
|
|
|
|
if (str == NULL) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("network uuid"));
|
|
|
|
goto error;
|
|
|
|
}
|
2007-08-09 20:19:12 +00:00
|
|
|
if (virUUIDParse(str, uuid) < 0) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("network uuid"));
|
|
|
|
goto error;
|
|
|
|
}
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(str);
|
2007-07-27 23:23:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
forward = virXPathBoolean("count(/network/forward) != 0", ctxt);
|
|
|
|
if (forward < 0) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("network forward"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
forwardDev = virXPathString("string(/network/forward/@dev)", ctxt);
|
|
|
|
|
|
|
|
|
|
|
|
ipaddress = virXPathString("string(/network/ip/@address)", ctxt);
|
|
|
|
if (ipaddress == NULL) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("ip address"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
ipnetmask = virXPathString("string(/network/ip/@netmask)", ctxt);
|
|
|
|
if (ipnetmask == NULL) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("ip netmask"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
dhcpstart = virXPathString("string(/network/ip/dhcp/range[1]/@start)", ctxt);
|
|
|
|
if (dhcpstart == NULL) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("ip address"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
dhcpend = virXPathString("string(/network/ip/dhcp/range[1]/@end)", ctxt);
|
|
|
|
if (dhcpend == NULL) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("ip address"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0 ; i < MAX_NETWORKS ; i++) {
|
|
|
|
if (!privconn->networks[i].active) {
|
|
|
|
handle = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (handle < 0)
|
|
|
|
return (-1);
|
|
|
|
|
|
|
|
privconn->networks[handle].active = 1;
|
|
|
|
privconn->networks[handle].running = 1;
|
|
|
|
strncpy(privconn->networks[handle].name, name, sizeof(privconn->networks[handle].name)-1);
|
|
|
|
privconn->networks[handle].name[sizeof(privconn->networks[handle].name)-1] = '\0';
|
|
|
|
strncpy(privconn->networks[handle].bridge, bridge ? bridge : name, sizeof(privconn->networks[handle].bridge)-1);
|
|
|
|
privconn->networks[handle].bridge[sizeof(privconn->networks[handle].bridge)-1] = '\0';
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(name);
|
2007-07-27 23:23:00 +00:00
|
|
|
name = NULL;
|
|
|
|
if (bridge) {
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(bridge);
|
2007-07-27 23:23:00 +00:00
|
|
|
bridge = NULL;
|
|
|
|
}
|
|
|
|
|
2007-08-09 20:19:12 +00:00
|
|
|
memmove(privconn->networks[handle].uuid, uuid, VIR_UUID_BUFLEN);
|
2007-07-27 23:23:00 +00:00
|
|
|
privconn->networks[handle].forward = forward;
|
|
|
|
if (forwardDev) {
|
|
|
|
strncpy(privconn->networks[handle].forwardDev, forwardDev, sizeof(privconn->networks[handle].forwardDev)-1);
|
|
|
|
privconn->networks[handle].forwardDev[sizeof(privconn->networks[handle].forwardDev)-1] = '\0';
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(forwardDev);
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
strncpy(privconn->networks[handle].ipAddress, ipaddress, sizeof(privconn->networks[handle].ipAddress)-1);
|
|
|
|
privconn->networks[handle].ipAddress[sizeof(privconn->networks[handle].ipAddress)-1] = '\0';
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(ipaddress);
|
2007-07-27 23:23:00 +00:00
|
|
|
strncpy(privconn->networks[handle].ipNetmask, ipnetmask, sizeof(privconn->networks[handle].ipNetmask)-1);
|
|
|
|
privconn->networks[handle].ipNetmask[sizeof(privconn->networks[handle].ipNetmask)-1] = '\0';
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(ipnetmask);
|
2007-07-27 23:23:00 +00:00
|
|
|
strncpy(privconn->networks[handle].dhcpStart, dhcpstart, sizeof(privconn->networks[handle].dhcpStart)-1);
|
|
|
|
privconn->networks[handle].dhcpStart[sizeof(privconn->networks[handle].dhcpStart)-1] = '\0';
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(dhcpstart);
|
2007-07-27 23:23:00 +00:00
|
|
|
strncpy(privconn->networks[handle].dhcpEnd, dhcpend, sizeof(privconn->networks[handle].dhcpEnd)-1);
|
|
|
|
privconn->networks[handle].dhcpEnd[sizeof(privconn->networks[handle].dhcpEnd)-1] = '\0';
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(dhcpend);
|
2008-01-30 19:50:14 +00:00
|
|
|
xmlXPathFreeContext(ctxt);
|
2007-07-27 23:23:00 +00:00
|
|
|
return (handle);
|
|
|
|
|
|
|
|
error:
|
2008-01-30 19:50:14 +00:00
|
|
|
xmlXPathFreeContext(ctxt);
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE (forwardDev);
|
|
|
|
VIR_FREE(ipaddress);
|
|
|
|
VIR_FREE(ipnetmask);
|
|
|
|
VIR_FREE(dhcpstart);
|
|
|
|
VIR_FREE(dhcpend);
|
|
|
|
VIR_FREE(name);
|
2007-07-27 23:23:00 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int testLoadNetworkFromDoc(virConnectPtr conn,
|
|
|
|
const char *doc) {
|
|
|
|
int ret;
|
|
|
|
xmlDocPtr xml;
|
|
|
|
if (!(xml = xmlReadDoc(BAD_CAST doc, "network.xml", NULL,
|
|
|
|
XML_PARSE_NOENT | XML_PARSE_NONET |
|
|
|
|
XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("network"));
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = testLoadNetwork(conn, xml);
|
|
|
|
|
|
|
|
xmlFreeDoc(xml);
|
|
|
|
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int testLoadNetworkFromFile(virConnectPtr conn,
|
|
|
|
const char *filename) {
|
|
|
|
int ret, fd;
|
|
|
|
xmlDocPtr xml;
|
|
|
|
|
|
|
|
if ((fd = open(filename, O_RDONLY)) < 0) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("load network definition file"));
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(xml = xmlReadFd(fd, filename, NULL,
|
|
|
|
XML_PARSE_NOENT | XML_PARSE_NONET |
|
|
|
|
XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("network"));
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = testLoadNetwork(conn, xml);
|
|
|
|
|
|
|
|
xmlFreeDoc(xml);
|
|
|
|
close(fd);
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
return (ret);
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testOpenDefault(virConnectPtr conn) {
|
2007-01-18 21:08:21 +00:00
|
|
|
int u;
|
|
|
|
struct timeval tv;
|
2008-05-29 19:20:22 +00:00
|
|
|
testConnPtr privconn;
|
|
|
|
if (VIR_ALLOC(privconn) < 0) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "testConn");
|
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
|
|
|
memset(privconn, 0, sizeof(testConn));
|
2007-01-18 21:08:21 +00:00
|
|
|
|
|
|
|
if (gettimeofday(&tv, NULL) < 0) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("getting time of day"));
|
2007-04-04 14:19:49 +00:00
|
|
|
return VIR_DRV_OPEN_ERROR;
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
strcpy(privconn->path, "/default");
|
|
|
|
privconn->nextDomID = 1;
|
|
|
|
privconn->numDomains = 1;
|
|
|
|
privconn->domains[0].active = 1;
|
|
|
|
privconn->domains[0].config = 1;
|
|
|
|
privconn->domains[0].id = privconn->nextDomID++;
|
|
|
|
privconn->domains[0].onReboot = VIR_DOMAIN_RESTART;
|
|
|
|
privconn->domains[0].onCrash = VIR_DOMAIN_RESTART;
|
|
|
|
privconn->domains[0].onPoweroff = VIR_DOMAIN_DESTROY;
|
|
|
|
strcpy(privconn->domains[0].name, "test");
|
Mon Jan 23 14:36:18 IST 2007 Mark McLoughlin <markmc@redhat.com>
* include/libvirt/libvirt.h.in: add VIR_UUID_BUFLEN and
VIR_UUID_STRING_BUFLEN
* libvirt/proxy/libvirt_proxy.c, libvirt/src/hash.c,
libvirt/src/internal.h, libvirt/src/libvirt.c,
libvirt/src/proxy_internal.c, libvirt/src/test.c,
libvirt/src/virsh.c, libvirt/src/xend_internal.c,
libvirt/src/xm_internal.c, libvirt/src/xml.c,
libvirt/python/libvir.c: use them
2007-01-23 14:39:45 +00:00
|
|
|
for (u = 0 ; u < VIR_UUID_BUFLEN ; u++) {
|
2007-07-27 23:23:00 +00:00
|
|
|
privconn->domains[0].uuid[u] = (u * 75)%255;
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
2007-07-27 23:23:00 +00:00
|
|
|
privconn->domains[0].info.maxMem = 8192 * 1024;
|
|
|
|
privconn->domains[0].info.memory = 2048 * 1024;
|
|
|
|
privconn->domains[0].info.state = VIR_DOMAIN_RUNNING;
|
|
|
|
privconn->domains[0].info.nrVirtCpu = 2;
|
|
|
|
privconn->domains[0].info.cpuTime = ((tv.tv_sec * 1000ll * 1000ll * 1000ll) + (tv.tv_usec * 1000ll));
|
|
|
|
|
|
|
|
|
|
|
|
privconn->numNetworks = 1;
|
|
|
|
privconn->networks[0].active = 1;
|
|
|
|
privconn->networks[0].config = 1;
|
|
|
|
privconn->networks[0].running = 1;
|
|
|
|
strcpy(privconn->networks[0].name, "default");
|
|
|
|
strcpy(privconn->networks[0].bridge, "default");
|
|
|
|
for (u = 0 ; u < VIR_UUID_BUFLEN ; u++) {
|
|
|
|
privconn->networks[0].uuid[u] = (u * 75)%255;
|
|
|
|
}
|
|
|
|
privconn->networks[0].forward = 1;
|
|
|
|
strcpy(privconn->networks[0].forwardDev, "eth0");
|
|
|
|
strcpy(privconn->networks[0].ipAddress, "192.168.122.1");
|
|
|
|
strcpy(privconn->networks[0].ipNetmask, "255.255.255.0");
|
|
|
|
strcpy(privconn->networks[0].dhcpStart, "192.168.122.128");
|
|
|
|
strcpy(privconn->networks[0].dhcpEnd, "192.168.122.253");
|
|
|
|
|
2008-04-04 07:31:24 +00:00
|
|
|
// Numa setup
|
|
|
|
privconn->numCells = 2;
|
|
|
|
for (u = 0; u < 2; ++u) {
|
|
|
|
privconn->cells[u].numCpus = 8;
|
|
|
|
privconn->cells[u].mem = (u + 1) * 2048 * 1024;
|
|
|
|
}
|
|
|
|
for (u = 0 ; u < 16 ; u++) {
|
|
|
|
privconn->cells[u % 2].cpus[(u / 2)] = u;
|
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
conn->privateData = privconn;
|
|
|
|
return (VIR_DRV_OPEN_SUCCESS);
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static char *testBuildFilename(const char *relativeTo,
|
2007-01-18 21:08:21 +00:00
|
|
|
const char *filename) {
|
|
|
|
char *offset;
|
|
|
|
int baseLen;
|
|
|
|
if (!filename || filename[0] == '\0')
|
|
|
|
return (NULL);
|
|
|
|
if (filename[0] == '/')
|
|
|
|
return strdup(filename);
|
|
|
|
|
2007-06-15 13:44:19 +00:00
|
|
|
offset = strrchr(relativeTo, '/');
|
2007-01-18 21:08:21 +00:00
|
|
|
if ((baseLen = (offset-relativeTo+1))) {
|
2008-05-29 19:20:22 +00:00
|
|
|
char *absFile;
|
|
|
|
if (VIR_ALLOC_N(absFile, baseLen + strlen(filename) + 1) < 0)
|
|
|
|
return NULL;
|
2007-01-18 21:08:21 +00:00
|
|
|
strncpy(absFile, relativeTo, baseLen);
|
|
|
|
absFile[baseLen] = '\0';
|
|
|
|
strcat(absFile, filename);
|
|
|
|
return absFile;
|
|
|
|
} else {
|
|
|
|
return strdup(filename);
|
|
|
|
}
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int testOpenFromFile(virConnectPtr conn,
|
2007-01-18 21:08:21 +00:00
|
|
|
const char *file) {
|
2007-07-27 23:23:00 +00:00
|
|
|
int fd = -1, i, ret;
|
2007-04-06 15:34:09 +00:00
|
|
|
long l;
|
|
|
|
char *str;
|
2007-07-27 23:23:00 +00:00
|
|
|
xmlDocPtr xml = NULL;
|
2007-01-18 21:08:21 +00:00
|
|
|
xmlNodePtr root = NULL;
|
2007-08-09 20:19:12 +00:00
|
|
|
xmlNodePtr *domains, *networks = NULL;
|
2007-01-18 21:08:21 +00:00
|
|
|
xmlXPathContextPtr ctxt = NULL;
|
|
|
|
virNodeInfoPtr nodeInfo;
|
2008-05-29 19:20:22 +00:00
|
|
|
testConnPtr privconn;
|
|
|
|
if (VIR_ALLOC(privconn) < 0) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY, "testConn");
|
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
2007-01-18 21:08:21 +00:00
|
|
|
|
|
|
|
if ((fd = open(file, O_RDONLY)) < 0) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("loading host definition file"));
|
|
|
|
goto error;
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
if (!(xml = xmlReadFd(fd, file, NULL,
|
|
|
|
XML_PARSE_NOENT | XML_PARSE_NONET |
|
|
|
|
XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("host"));
|
2007-01-18 21:08:21 +00:00
|
|
|
goto error;
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
2007-01-18 21:08:21 +00:00
|
|
|
close(fd);
|
|
|
|
fd = -1;
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
root = xmlDocGetRootElement(xml);
|
|
|
|
if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "node"))) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(NULL, NULL, NULL, VIR_ERR_XML_ERROR, _("node"));
|
2007-01-18 21:08:21 +00:00
|
|
|
goto error;
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
ctxt = xmlXPathNewContext(xml);
|
|
|
|
if (ctxt == NULL) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("creating xpath context"));
|
2007-01-18 21:08:21 +00:00
|
|
|
goto error;
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
2007-01-18 21:08:21 +00:00
|
|
|
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
conn->privateData = privconn;
|
|
|
|
privconn->nextDomID = 1;
|
|
|
|
privconn->numDomains = 0;
|
|
|
|
privconn->numNetworks = 0;
|
2008-04-04 07:31:24 +00:00
|
|
|
privconn->numCells = 0;
|
2007-07-27 23:23:00 +00:00
|
|
|
strncpy(privconn->path, file, PATH_MAX-1);
|
|
|
|
privconn->path[PATH_MAX-1] = '\0';
|
|
|
|
memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));
|
|
|
|
|
|
|
|
nodeInfo = &privconn->nodeInfo;
|
2007-04-06 15:34:09 +00:00
|
|
|
ret = virXPathLong("string(/node/cpu/nodes[1])", ctxt, &l);
|
|
|
|
if (ret == 0) {
|
|
|
|
nodeInfo->nodes = l;
|
|
|
|
} else if (ret == -2) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(NULL, NULL, NULL, VIR_ERR_XML_ERROR, _("node cpu numa nodes"));
|
|
|
|
goto error;
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2007-04-06 15:34:09 +00:00
|
|
|
ret = virXPathLong("string(/node/cpu/sockets[1])", ctxt, &l);
|
|
|
|
if (ret == 0) {
|
|
|
|
nodeInfo->sockets = l;
|
|
|
|
} else if (ret == -2) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(NULL, NULL, NULL, VIR_ERR_XML_ERROR, _("node cpu sockets"));
|
|
|
|
goto error;
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2007-04-06 15:34:09 +00:00
|
|
|
ret = virXPathLong("string(/node/cpu/cores[1])", ctxt, &l);
|
|
|
|
if (ret == 0) {
|
|
|
|
nodeInfo->cores = l;
|
|
|
|
} else if (ret == -2) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(NULL, NULL, NULL, VIR_ERR_XML_ERROR, _("node cpu cores"));
|
|
|
|
goto error;
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
|
|
|
|
2007-04-06 15:34:09 +00:00
|
|
|
ret = virXPathLong("string(/node/cpu/threads[1])", ctxt, &l);
|
|
|
|
if (ret == 0) {
|
|
|
|
nodeInfo->threads = l;
|
|
|
|
} else if (ret == -2) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(NULL, NULL, NULL, VIR_ERR_XML_ERROR, _("node cpu threads"));
|
|
|
|
goto error;
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
2007-04-06 15:34:09 +00:00
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
nodeInfo->cpus = nodeInfo->cores * nodeInfo->threads * nodeInfo->sockets * nodeInfo->nodes;
|
2007-04-06 15:34:09 +00:00
|
|
|
ret = virXPathLong("string(/node/cpu/active[1])", ctxt, &l);
|
|
|
|
if (ret == 0) {
|
|
|
|
if (l < nodeInfo->cpus) {
|
2007-07-27 23:23:00 +00:00
|
|
|
nodeInfo->cpus = l;
|
|
|
|
}
|
2007-04-06 15:34:09 +00:00
|
|
|
} else if (ret == -2) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(NULL, NULL, NULL, VIR_ERR_XML_ERROR, _("node active cpu"));
|
|
|
|
goto error;
|
2007-04-06 15:34:09 +00:00
|
|
|
}
|
|
|
|
ret = virXPathLong("string(/node/cpu/mhz[1])", ctxt, &l);
|
|
|
|
if (ret == 0) {
|
|
|
|
nodeInfo->mhz = l;
|
|
|
|
} else if (ret == -2) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(NULL, NULL, NULL, VIR_ERR_XML_ERROR, _("node cpu mhz"));
|
|
|
|
goto error;
|
2007-04-06 15:34:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
str = virXPathString("string(/node/cpu/model[1])", ctxt);
|
|
|
|
if (str != NULL) {
|
|
|
|
strncpy(nodeInfo->model, str, sizeof(nodeInfo->model)-1);
|
2007-01-18 21:08:21 +00:00
|
|
|
nodeInfo->model[sizeof(nodeInfo->model)-1] = '\0';
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(str);
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
|
|
|
|
2007-04-06 15:34:09 +00:00
|
|
|
ret = virXPathLong("string(/node/memory[1])", ctxt, &l);
|
|
|
|
if (ret == 0) {
|
|
|
|
nodeInfo->memory = l;
|
|
|
|
} else if (ret == -2) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(NULL, NULL, NULL, VIR_ERR_XML_ERROR, _("node memory"));
|
|
|
|
goto error;
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2007-04-06 15:34:09 +00:00
|
|
|
ret = virXPathNodeSet("/node/domain", ctxt, &domains);
|
|
|
|
if (ret < 0) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(NULL, NULL, NULL, VIR_ERR_XML_ERROR, _("node domain list"));
|
2007-01-18 21:08:21 +00:00
|
|
|
goto error;
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2007-04-06 15:34:09 +00:00
|
|
|
for (i = 0 ; i < ret ; i++) {
|
|
|
|
xmlChar *domFile = xmlGetProp(domains[i], BAD_CAST "file");
|
2007-01-18 21:08:21 +00:00
|
|
|
char *absFile = testBuildFilename(file, (const char *)domFile);
|
2007-07-27 23:23:00 +00:00
|
|
|
int domid = privconn->nextDomID++, handle;
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(domFile);
|
2007-01-18 21:08:21 +00:00
|
|
|
if (!absFile) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("resolving domain filename"));
|
2007-01-18 21:08:21 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-07-27 23:23:00 +00:00
|
|
|
if ((handle = testLoadDomainFromFile(conn, domid, absFile)) < 0) {
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(absFile);
|
2007-01-18 21:08:21 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-07-27 23:23:00 +00:00
|
|
|
privconn->domains[handle].config = 1;
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(absFile);
|
2007-07-27 23:23:00 +00:00
|
|
|
privconn->numDomains++;
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
2007-07-27 23:23:00 +00:00
|
|
|
if (domains != NULL) {
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(domains);
|
2007-07-27 23:23:00 +00:00
|
|
|
domains = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ret = virXPathNodeSet("/node/network", ctxt, &networks);
|
|
|
|
if (ret > 0) {
|
|
|
|
for (i = 0 ; i < ret ; i++) {
|
|
|
|
xmlChar *netFile = xmlGetProp(networks[i], BAD_CAST "file");
|
|
|
|
char *absFile = testBuildFilename(file, (const char *)netFile);
|
|
|
|
int handle;
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(netFile);
|
2007-07-27 23:23:00 +00:00
|
|
|
if (!absFile) {
|
|
|
|
testError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("resolving network filename"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if ((handle = testLoadNetworkFromFile(conn, absFile)) < 0) {
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(absFile);
|
2007-07-27 23:23:00 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
privconn->networks[handle].config = 1;
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(absFile);
|
2007-07-27 23:23:00 +00:00
|
|
|
privconn->numNetworks++;
|
|
|
|
}
|
|
|
|
if (networks != NULL) {
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(networks);
|
2007-07-27 23:23:00 +00:00
|
|
|
networks = NULL;
|
|
|
|
}
|
|
|
|
}
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2008-01-30 19:50:14 +00:00
|
|
|
xmlXPathFreeContext(ctxt);
|
2007-01-18 21:08:21 +00:00
|
|
|
xmlFreeDoc(xml);
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
return (0);
|
2006-08-16 16:36:39 +00:00
|
|
|
|
|
|
|
error:
|
2008-01-30 19:50:14 +00:00
|
|
|
xmlXPathFreeContext(ctxt);
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(domains);
|
|
|
|
VIR_FREE(networks);
|
2007-01-18 21:08:21 +00:00
|
|
|
if (xml)
|
|
|
|
xmlFreeDoc(xml);
|
|
|
|
if (fd != -1)
|
|
|
|
close(fd);
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(privconn);
|
2007-07-27 23:23:00 +00:00
|
|
|
conn->privateData = NULL;
|
2007-04-04 14:19:49 +00:00
|
|
|
return VIR_DRV_OPEN_ERROR;
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
static int getDomainIndex(virDomainPtr domain) {
|
|
|
|
int i;
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_CONNECTION(domain->conn, -1);
|
2007-04-04 14:19:49 +00:00
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
for (i = 0 ; i < MAX_DOMAINS ; i++) {
|
2007-01-22 16:25:27 +00:00
|
|
|
if (domain->id >= 0) {
|
2007-07-27 23:23:00 +00:00
|
|
|
if (domain->id == privconn->domains[i].id)
|
2007-01-18 21:08:21 +00:00
|
|
|
return (i);
|
|
|
|
} else {
|
2007-07-27 23:23:00 +00:00
|
|
|
if (STREQ(domain->name, privconn->domains[i].name))
|
2007-01-18 21:08:21 +00:00
|
|
|
return (i);
|
|
|
|
}
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
2006-06-06 03:32:51 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int getNetworkIndex(virNetworkPtr network) {
|
|
|
|
int i;
|
|
|
|
GET_CONNECTION(network->conn, -1);
|
|
|
|
|
|
|
|
for (i = 0 ; i < MAX_NETWORKS ; i++) {
|
|
|
|
if (STREQ(network->name, privconn->networks[i].name))
|
|
|
|
return (i);
|
|
|
|
}
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int testOpen(virConnectPtr conn,
|
2007-11-14 11:40:57 +00:00
|
|
|
xmlURIPtr uri,
|
2007-12-05 18:28:05 +00:00
|
|
|
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
2007-07-27 23:23:00 +00:00
|
|
|
int flags ATTRIBUTE_UNUSED)
|
2006-06-06 03:32:51 +00:00
|
|
|
{
|
2007-07-27 23:23:00 +00:00
|
|
|
int ret;
|
2006-06-06 03:32:51 +00:00
|
|
|
|
2007-11-14 11:40:57 +00:00
|
|
|
if (!uri)
|
2007-04-04 14:19:49 +00:00
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
2006-06-06 03:32:51 +00:00
|
|
|
|
2008-05-14 19:51:24 +00:00
|
|
|
if (!uri->scheme || STRNEQ(uri->scheme, "test"))
|
2007-04-04 14:19:49 +00:00
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
2006-06-06 03:32:51 +00:00
|
|
|
|
2007-06-20 10:01:14 +00:00
|
|
|
/* Remote driver should handle these. */
|
2007-11-14 11:40:57 +00:00
|
|
|
if (uri->server)
|
2007-06-20 10:01:14 +00:00
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
|
|
|
2007-11-14 11:40:57 +00:00
|
|
|
if (uri->server)
|
2007-06-26 22:57:41 +00:00
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
|
|
|
2007-04-18 10:14:07 +00:00
|
|
|
/* From this point on, the connection is for us. */
|
|
|
|
if (!uri->path
|
|
|
|
|| uri->path[0] == '\0'
|
|
|
|
|| (uri->path[0] == '/' && uri->path[1] == '\0')) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError (NULL, NULL, NULL, VIR_ERR_INVALID_ARG,
|
2007-04-18 10:14:07 +00:00
|
|
|
_("testOpen: supply a path or use test:///default"));
|
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
2006-06-06 03:32:51 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
if (STREQ(uri->path, "/default"))
|
|
|
|
ret = testOpenDefault(conn);
|
|
|
|
else
|
2007-01-18 21:08:21 +00:00
|
|
|
ret = testOpenFromFile(conn,
|
|
|
|
uri->path);
|
|
|
|
|
|
|
|
return (ret);
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testClose(virConnectPtr conn)
|
2006-06-06 03:32:51 +00:00
|
|
|
{
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_CONNECTION(conn, -1);
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE (privconn);
|
2007-07-27 23:23:00 +00:00
|
|
|
conn->privateData = conn;
|
2007-04-04 14:19:49 +00:00
|
|
|
return 0;
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long *hvVer)
|
2006-06-06 03:32:51 +00:00
|
|
|
{
|
2007-01-18 21:08:21 +00:00
|
|
|
*hvVer = 2;
|
|
|
|
return (0);
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static char *testGetHostname (virConnectPtr conn)
|
2007-06-26 11:42:46 +00:00
|
|
|
{
|
|
|
|
int r;
|
|
|
|
char hostname [HOST_NAME_MAX+1], *str;
|
|
|
|
|
|
|
|
r = gethostname (hostname, HOST_NAME_MAX+1);
|
|
|
|
if (r == -1) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError (conn, NULL, NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno));
|
2007-06-26 11:42:46 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
str = strdup (hostname);
|
|
|
|
if (str == NULL) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError (conn, NULL, NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno));
|
2007-06-26 11:42:46 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static char * testGetURI (virConnectPtr conn)
|
2007-06-26 11:42:46 +00:00
|
|
|
{
|
|
|
|
char *uri;
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_CONNECTION(conn, NULL);
|
2007-06-26 11:42:46 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
if (asprintf (&uri, "test://%s", privconn->path) == -1) {
|
|
|
|
testError (conn, NULL, NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno));
|
2007-06-26 11:42:46 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return uri;
|
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|
|
|
const char *type ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return 32;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int testNodeGetInfo(virConnectPtr conn,
|
|
|
|
virNodeInfoPtr info)
|
2006-06-06 03:32:51 +00:00
|
|
|
{
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_CONNECTION(conn, -1);
|
|
|
|
memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo));
|
2007-01-18 21:08:21 +00:00
|
|
|
return (0);
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static char *testGetCapabilities (virConnectPtr conn)
|
2007-03-15 17:24:56 +00:00
|
|
|
{
|
2008-02-27 04:35:08 +00:00
|
|
|
virCapsPtr caps;
|
|
|
|
virCapsGuestPtr guest;
|
|
|
|
char *xml;
|
2008-04-08 09:26:24 +00:00
|
|
|
const char *guest_types[] = { "hvm", "xen" };
|
2008-04-04 07:31:24 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
GET_CONNECTION(conn, -1);
|
2008-02-27 04:35:08 +00:00
|
|
|
|
|
|
|
if ((caps = virCapabilitiesNew(TEST_MODEL, 0, 0)) == NULL)
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
if (virCapabilitiesAddHostFeature(caps, "pae") < 0)
|
|
|
|
goto no_memory;
|
|
|
|
if (virCapabilitiesAddHostFeature(caps ,"nonpae") < 0)
|
|
|
|
goto no_memory;
|
|
|
|
|
2008-04-04 07:31:24 +00:00
|
|
|
for (i = 0; i < privconn->numCells; ++i) {
|
|
|
|
if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].numCpus,
|
|
|
|
privconn->cells[i].cpus) < 0)
|
|
|
|
goto no_memory;
|
|
|
|
}
|
2008-02-27 04:35:08 +00:00
|
|
|
|
2008-04-08 09:26:24 +00:00
|
|
|
for (i = 0; i < (sizeof(guest_types)/sizeof(guest_types[0])); ++i) {
|
2008-02-27 04:35:08 +00:00
|
|
|
|
2008-04-08 09:26:24 +00:00
|
|
|
if ((guest = virCapabilitiesAddGuest(caps,
|
|
|
|
guest_types[i],
|
|
|
|
TEST_MODEL,
|
|
|
|
TEST_MODEL_WORDSIZE,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL)) == NULL)
|
|
|
|
goto no_memory;
|
2008-02-27 04:35:08 +00:00
|
|
|
|
2008-04-08 09:26:24 +00:00
|
|
|
if (virCapabilitiesAddGuestDomain(guest,
|
|
|
|
"test",
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL) == NULL)
|
|
|
|
goto no_memory;
|
2008-02-27 04:35:08 +00:00
|
|
|
|
2008-04-08 09:26:24 +00:00
|
|
|
if (virCapabilitiesAddGuestFeature(guest, "pae", 1, 1) == NULL)
|
|
|
|
goto no_memory;
|
|
|
|
if (virCapabilitiesAddGuestFeature(guest ,"nonpae", 1, 1) == NULL)
|
|
|
|
goto no_memory;
|
|
|
|
}
|
2008-02-27 04:35:08 +00:00
|
|
|
|
|
|
|
if ((xml = virCapabilitiesFormatXML(caps)) == NULL)
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
virCapabilitiesFree(caps);
|
|
|
|
|
|
|
|
return xml;
|
|
|
|
|
|
|
|
no_memory:
|
|
|
|
virCapabilitiesFree(caps);
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, __FUNCTION__);
|
|
|
|
return NULL;
|
2007-03-15 17:24:56 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testNumOfDomains(virConnectPtr conn)
|
2006-06-06 03:32:51 +00:00
|
|
|
{
|
2007-01-18 21:08:21 +00:00
|
|
|
int numActive = 0, i;
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_CONNECTION(conn, -1);
|
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
for (i = 0 ; i < MAX_DOMAINS ; i++) {
|
2007-07-27 23:23:00 +00:00
|
|
|
if (!privconn->domains[i].active ||
|
|
|
|
privconn->domains[i].info.state == VIR_DOMAIN_SHUTOFF)
|
2007-01-18 21:08:21 +00:00
|
|
|
continue;
|
|
|
|
numActive++;
|
|
|
|
}
|
|
|
|
return (numActive);
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static virDomainPtr
|
2006-08-16 16:36:39 +00:00
|
|
|
testDomainCreateLinux(virConnectPtr conn, const char *xmlDesc,
|
2007-01-18 21:08:21 +00:00
|
|
|
unsigned int flags ATTRIBUTE_UNUSED)
|
2006-08-16 16:36:39 +00:00
|
|
|
{
|
2007-07-27 23:23:00 +00:00
|
|
|
int domid, handle = -1;
|
2007-01-18 21:08:21 +00:00
|
|
|
virDomainPtr dom;
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_CONNECTION(conn, NULL);
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
if (xmlDesc == NULL) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
2007-01-18 21:08:21 +00:00
|
|
|
return (NULL);
|
|
|
|
}
|
2007-07-27 23:23:00 +00:00
|
|
|
|
|
|
|
if (privconn->numDomains == MAX_DOMAINS) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("too many domains"));
|
2007-01-18 21:08:21 +00:00
|
|
|
return (NULL);
|
|
|
|
}
|
2007-04-04 14:19:49 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
domid = privconn->nextDomID++;
|
|
|
|
if ((handle = testLoadDomainFromDoc(conn, domid, xmlDesc)) < 0)
|
2007-01-18 21:08:21 +00:00
|
|
|
return (NULL);
|
2007-07-27 23:23:00 +00:00
|
|
|
privconn->domains[handle].config = 0;
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
dom = virGetDomain(conn, privconn->domains[handle].name, privconn->domains[handle].uuid);
|
2007-07-06 15:02:09 +00:00
|
|
|
if (dom == NULL) return NULL;
|
2007-07-27 23:23:00 +00:00
|
|
|
privconn->numDomains++;
|
2007-01-18 21:08:21 +00:00
|
|
|
return (dom);
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static virDomainPtr testLookupDomainByID(virConnectPtr conn,
|
|
|
|
int id)
|
2006-06-06 03:32:51 +00:00
|
|
|
{
|
2007-01-18 21:08:21 +00:00
|
|
|
virDomainPtr dom;
|
|
|
|
int i, idx = -1;
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_CONNECTION(conn, NULL);
|
2007-01-18 21:08:21 +00:00
|
|
|
|
|
|
|
for (i = 0 ; i < MAX_DOMAINS ; i++) {
|
2007-07-27 23:23:00 +00:00
|
|
|
if (privconn->domains[i].active &&
|
|
|
|
privconn->domains[i].id == id) {
|
2007-01-18 21:08:21 +00:00
|
|
|
idx = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (idx < 0) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError (conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
|
2007-01-18 21:08:21 +00:00
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
dom = virGetDomain(conn, privconn->domains[idx].name, privconn->domains[idx].uuid);
|
2007-07-06 15:02:09 +00:00
|
|
|
if (dom == NULL) return NULL;
|
2007-01-22 16:25:27 +00:00
|
|
|
dom->id = id;
|
2007-01-18 21:08:21 +00:00
|
|
|
return (dom);
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static virDomainPtr testLookupDomainByUUID(virConnectPtr conn,
|
|
|
|
const unsigned char *uuid)
|
2006-06-06 03:32:51 +00:00
|
|
|
{
|
2007-07-06 14:56:15 +00:00
|
|
|
virDomainPtr dom;
|
2007-01-18 21:08:21 +00:00
|
|
|
int i, idx = -1;
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_CONNECTION(conn, NULL);
|
2007-07-06 14:56:15 +00:00
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
for (i = 0 ; i < MAX_DOMAINS ; i++) {
|
2007-07-27 23:23:00 +00:00
|
|
|
if (privconn->domains[i].active &&
|
|
|
|
memcmp(uuid, privconn->domains[i].uuid, VIR_UUID_BUFLEN) == 0) {
|
2007-01-18 21:08:21 +00:00
|
|
|
idx = i;
|
|
|
|
break;
|
|
|
|
}
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
2007-07-06 14:56:15 +00:00
|
|
|
|
|
|
|
if (idx < 0) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError (conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
|
2007-07-06 14:56:15 +00:00
|
|
|
return NULL;
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
2007-07-06 14:56:15 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
dom = virGetDomain(conn, privconn->domains[idx].name, privconn->domains[idx].uuid);
|
2007-07-06 15:02:09 +00:00
|
|
|
if (dom == NULL) return NULL;
|
2007-07-27 23:23:00 +00:00
|
|
|
dom->id = privconn->domains[idx].id;
|
2007-07-06 14:56:15 +00:00
|
|
|
|
|
|
|
return dom;
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static virDomainPtr testLookupDomainByName(virConnectPtr conn,
|
|
|
|
const char *name)
|
2006-06-06 03:32:51 +00:00
|
|
|
{
|
2007-07-06 14:56:15 +00:00
|
|
|
virDomainPtr dom;
|
2007-01-18 21:08:21 +00:00
|
|
|
int i, idx = -1;
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_CONNECTION(conn, NULL);
|
2007-07-06 14:56:15 +00:00
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
for (i = 0 ; i < MAX_DOMAINS ; i++) {
|
2007-07-27 23:23:00 +00:00
|
|
|
if (privconn->domains[i].active &&
|
2008-05-14 19:51:24 +00:00
|
|
|
STREQ(name, privconn->domains[i].name)) {
|
2007-01-18 21:08:21 +00:00
|
|
|
idx = i;
|
|
|
|
break;
|
|
|
|
}
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
2007-07-06 14:56:15 +00:00
|
|
|
|
|
|
|
if (idx < 0) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError (conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
|
2007-07-06 14:56:15 +00:00
|
|
|
return NULL;
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
2007-07-06 14:56:15 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
dom = virGetDomain(conn, privconn->domains[idx].name, privconn->domains[idx].uuid);
|
2007-07-06 15:02:09 +00:00
|
|
|
if (dom == NULL) return NULL;
|
2007-07-27 23:23:00 +00:00
|
|
|
dom->id = privconn->domains[idx].id;
|
2007-07-06 14:56:15 +00:00
|
|
|
|
|
|
|
return dom;
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testListDomains (virConnectPtr conn,
|
|
|
|
int *ids,
|
|
|
|
int maxids)
|
2006-06-06 03:32:51 +00:00
|
|
|
{
|
2007-01-18 21:08:21 +00:00
|
|
|
int n, i;
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_CONNECTION(conn, -1);
|
2007-01-18 21:08:21 +00:00
|
|
|
|
|
|
|
for (i = 0, n = 0 ; i < MAX_DOMAINS && n < maxids ; i++) {
|
2007-07-27 23:23:00 +00:00
|
|
|
if (privconn->domains[i].active &&
|
|
|
|
privconn->domains[i].info.state != VIR_DOMAIN_SHUTOFF) {
|
|
|
|
ids[n++] = privconn->domains[i].id;
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
2007-01-18 21:08:21 +00:00
|
|
|
return (n);
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testDestroyDomain (virDomainPtr domain)
|
2006-06-06 03:32:51 +00:00
|
|
|
{
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_DOMAIN(domain, -1);
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
if (privdom->config) {
|
|
|
|
privdom->info.state = VIR_DOMAIN_SHUTOFF;
|
|
|
|
privdom->id = -1;
|
|
|
|
domain->id = -1;
|
|
|
|
} else {
|
|
|
|
privdom->active = 0;
|
|
|
|
}
|
2007-01-18 21:08:21 +00:00
|
|
|
return (0);
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testResumeDomain (virDomainPtr domain)
|
2006-06-06 03:32:51 +00:00
|
|
|
{
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_DOMAIN(domain, -1);
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
if (privdom->info.state != VIR_DOMAIN_PAUSED) {
|
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR, "domain not paused");
|
|
|
|
return -1;
|
|
|
|
}
|
2007-04-04 14:19:49 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
privdom->info.state = VIR_DOMAIN_RUNNING;
|
2007-01-18 21:08:21 +00:00
|
|
|
return (0);
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testPauseDomain (virDomainPtr domain)
|
2006-06-06 03:32:51 +00:00
|
|
|
{
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_DOMAIN(domain, -1);
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
if (privdom->info.state == VIR_DOMAIN_SHUTOFF ||
|
|
|
|
privdom->info.state == VIR_DOMAIN_PAUSED) {
|
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR, "domain not running");
|
|
|
|
return -1;
|
|
|
|
}
|
2007-04-04 14:19:49 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
privdom->info.state = VIR_DOMAIN_PAUSED;
|
2007-01-18 21:08:21 +00:00
|
|
|
return (0);
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testShutdownDomain (virDomainPtr domain)
|
2006-06-14 23:58:34 +00:00
|
|
|
{
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_DOMAIN(domain, -1);
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
if (privdom->info.state == VIR_DOMAIN_SHUTOFF) {
|
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR, "domain not running");
|
|
|
|
return -1;
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
2006-06-14 23:58:34 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
privdom->info.state = VIR_DOMAIN_SHUTOFF;
|
2007-01-22 16:25:27 +00:00
|
|
|
domain->id = -1;
|
2007-07-27 23:23:00 +00:00
|
|
|
privdom->id = -1;
|
2007-01-18 21:08:21 +00:00
|
|
|
|
|
|
|
return (0);
|
2006-06-14 23:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Similar behaviour as shutdown */
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testRebootDomain (virDomainPtr domain, virDomainRestart action)
|
2006-06-14 23:58:34 +00:00
|
|
|
{
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_DOMAIN(domain, -1);
|
2007-01-18 21:08:21 +00:00
|
|
|
|
|
|
|
if (!action)
|
|
|
|
action = VIR_DOMAIN_RESTART;
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
privdom->info.state = VIR_DOMAIN_SHUTDOWN;
|
2007-01-18 21:08:21 +00:00
|
|
|
switch (action) {
|
|
|
|
case VIR_DOMAIN_DESTROY:
|
2007-07-27 23:23:00 +00:00
|
|
|
privdom->info.state = VIR_DOMAIN_SHUTOFF;
|
|
|
|
domain->id = -1;
|
|
|
|
privdom->id = -1;
|
2007-01-18 21:08:21 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_RESTART:
|
2007-07-27 23:23:00 +00:00
|
|
|
privdom->info.state = VIR_DOMAIN_RUNNING;
|
2007-01-18 21:08:21 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_PRESERVE:
|
2007-07-27 23:23:00 +00:00
|
|
|
privdom->info.state = VIR_DOMAIN_SHUTOFF;
|
|
|
|
domain->id = -1;
|
|
|
|
privdom->id = -1;
|
2007-01-18 21:08:21 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_RENAME_RESTART:
|
2007-07-27 23:23:00 +00:00
|
|
|
privdom->info.state = VIR_DOMAIN_RUNNING;
|
2007-01-18 21:08:21 +00:00
|
|
|
break;
|
2006-06-14 23:58:34 +00:00
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
default:
|
2007-07-27 23:23:00 +00:00
|
|
|
privdom->info.state = VIR_DOMAIN_SHUTOFF;
|
|
|
|
domain->id = -1;
|
|
|
|
privdom->id = -1;
|
2007-01-18 21:08:21 +00:00
|
|
|
break;
|
|
|
|
}
|
2006-06-14 23:58:34 +00:00
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
return (0);
|
2006-06-14 23:58:34 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testGetDomainInfo (virDomainPtr domain,
|
|
|
|
virDomainInfoPtr info)
|
2006-06-06 03:32:51 +00:00
|
|
|
{
|
2007-01-18 21:08:21 +00:00
|
|
|
struct timeval tv;
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_DOMAIN(domain, -1);
|
2007-01-18 21:08:21 +00:00
|
|
|
|
|
|
|
if (gettimeofday(&tv, NULL) < 0) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR, _("getting time of day"));
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
if (privdom->info.state == VIR_DOMAIN_SHUTOFF) {
|
|
|
|
privdom->info.cpuTime = 0;
|
|
|
|
privdom->info.memory = 0;
|
2007-01-18 21:08:21 +00:00
|
|
|
} else {
|
2007-07-27 23:23:00 +00:00
|
|
|
privdom->info.cpuTime = ((tv.tv_sec * 1000ll * 1000ll * 1000ll) + (tv.tv_usec * 1000ll));
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
2007-07-27 23:23:00 +00:00
|
|
|
memcpy(info, &privdom->info, sizeof(virDomainInfo));
|
2007-01-18 21:08:21 +00:00
|
|
|
return (0);
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static char *testDomainDumpXML(virDomainPtr domain, int flags);
|
2006-11-08 18:54:57 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
#define TEST_SAVE_MAGIC "TestGuestMagic"
|
|
|
|
|
|
|
|
static int testDomainSave(virDomainPtr domain,
|
|
|
|
const char *path)
|
|
|
|
{
|
|
|
|
char *xml;
|
|
|
|
int fd, len;
|
|
|
|
GET_DOMAIN(domain, -1);
|
2007-04-04 14:19:49 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
xml = testDomainDumpXML(domain, 0);
|
2008-01-30 19:52:16 +00:00
|
|
|
if (xml == NULL) {
|
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-03-27 14:01:59 +00:00
|
|
|
_("cannot allocate space for metadata"));
|
2008-01-30 19:52:16 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
2007-07-27 23:23:00 +00:00
|
|
|
|
|
|
|
if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
|
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-03-27 14:01:59 +00:00
|
|
|
_("cannot save domain"));
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
2007-07-27 23:23:00 +00:00
|
|
|
len = strlen(xml);
|
Use safewrite in place of write, in many cases.
Also add "make syntax-check" rules to ensure no new uses sneak in.
There are many uses of write like this:
if (write (fd, xml, towrite) != towrite)
return -1;
The problem is that the syscall can succeed, yet write less than
the requested number of bytes, so the caller should retry
rather than simply failing.
This patch changes most of them to use util.c's safewrite wrapper,
which encapsulates the process. Also, there were a few cases in
which the retry loop was open-coded, and I replaced those, too.
* Makefile.maint (sc_avoid_write): New rule, to avoid recurrence.
* .x-sc_avoid_write: New file. Record two legitimate exemptions.
* qemud/qemud.c (sig_handler, qemudClientWriteBuf): Use safewrite, not write.
* src/conf.c (__virConfWriteFile): Likewise.
* src/qemu_conf.c (qemudSaveConfig, qemudSaveNetworkConfig): Likewise.
* src/qemu_driver.c (qemudWaitForMonitor, qemudStartVMDaemon)
(qemudVMData, PROC_IP_FORWARD): Likewise.
* proxy/libvirt_proxy.c: Include "util.h".
(proxyWriteClientSocket): Use safewrite.
* src/test.c (testDomainSave, testDomainCoreDump): Likewise.
* src/proxy_internal.c (virProxyWriteClientSocket): Likewise.
* src/virsh.c: Include "util-lib.h".
(vshOutputLogFile): Use safewrite.
* src/console.c: Include "util-lib.h".
(vshRunConsole): Use safewrite.
2008-02-22 15:55:04 +00:00
|
|
|
if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-03-27 14:01:59 +00:00
|
|
|
_("cannot write header"));
|
2007-07-27 23:23:00 +00:00
|
|
|
close(fd);
|
|
|
|
return (-1);
|
|
|
|
}
|
Use safewrite in place of write, in many cases.
Also add "make syntax-check" rules to ensure no new uses sneak in.
There are many uses of write like this:
if (write (fd, xml, towrite) != towrite)
return -1;
The problem is that the syscall can succeed, yet write less than
the requested number of bytes, so the caller should retry
rather than simply failing.
This patch changes most of them to use util.c's safewrite wrapper,
which encapsulates the process. Also, there were a few cases in
which the retry loop was open-coded, and I replaced those, too.
* Makefile.maint (sc_avoid_write): New rule, to avoid recurrence.
* .x-sc_avoid_write: New file. Record two legitimate exemptions.
* qemud/qemud.c (sig_handler, qemudClientWriteBuf): Use safewrite, not write.
* src/conf.c (__virConfWriteFile): Likewise.
* src/qemu_conf.c (qemudSaveConfig, qemudSaveNetworkConfig): Likewise.
* src/qemu_driver.c (qemudWaitForMonitor, qemudStartVMDaemon)
(qemudVMData, PROC_IP_FORWARD): Likewise.
* proxy/libvirt_proxy.c: Include "util.h".
(proxyWriteClientSocket): Use safewrite.
* src/test.c (testDomainSave, testDomainCoreDump): Likewise.
* src/proxy_internal.c (virProxyWriteClientSocket): Likewise.
* src/virsh.c: Include "util-lib.h".
(vshOutputLogFile): Use safewrite.
* src/console.c: Include "util-lib.h".
(vshRunConsole): Use safewrite.
2008-02-22 15:55:04 +00:00
|
|
|
if (safewrite(fd, (char*)&len, sizeof(len)) < 0) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-03-27 14:01:59 +00:00
|
|
|
_("cannot write metadata length"));
|
2007-07-27 23:23:00 +00:00
|
|
|
close(fd);
|
|
|
|
return (-1);
|
|
|
|
}
|
Use safewrite in place of write, in many cases.
Also add "make syntax-check" rules to ensure no new uses sneak in.
There are many uses of write like this:
if (write (fd, xml, towrite) != towrite)
return -1;
The problem is that the syscall can succeed, yet write less than
the requested number of bytes, so the caller should retry
rather than simply failing.
This patch changes most of them to use util.c's safewrite wrapper,
which encapsulates the process. Also, there were a few cases in
which the retry loop was open-coded, and I replaced those, too.
* Makefile.maint (sc_avoid_write): New rule, to avoid recurrence.
* .x-sc_avoid_write: New file. Record two legitimate exemptions.
* qemud/qemud.c (sig_handler, qemudClientWriteBuf): Use safewrite, not write.
* src/conf.c (__virConfWriteFile): Likewise.
* src/qemu_conf.c (qemudSaveConfig, qemudSaveNetworkConfig): Likewise.
* src/qemu_driver.c (qemudWaitForMonitor, qemudStartVMDaemon)
(qemudVMData, PROC_IP_FORWARD): Likewise.
* proxy/libvirt_proxy.c: Include "util.h".
(proxyWriteClientSocket): Use safewrite.
* src/test.c (testDomainSave, testDomainCoreDump): Likewise.
* src/proxy_internal.c (virProxyWriteClientSocket): Likewise.
* src/virsh.c: Include "util-lib.h".
(vshOutputLogFile): Use safewrite.
* src/console.c: Include "util-lib.h".
(vshRunConsole): Use safewrite.
2008-02-22 15:55:04 +00:00
|
|
|
if (safewrite(fd, xml, len) < 0) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-03-27 14:01:59 +00:00
|
|
|
_("cannot write metadata"));
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(xml);
|
2007-07-27 23:23:00 +00:00
|
|
|
close(fd);
|
|
|
|
return (-1);
|
|
|
|
}
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(xml);
|
2007-07-27 23:23:00 +00:00
|
|
|
if (close(fd) < 0) {
|
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-03-27 14:01:59 +00:00
|
|
|
_("cannot save domain data"));
|
2007-07-27 23:23:00 +00:00
|
|
|
close(fd);
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
if (privdom->config) {
|
|
|
|
privdom->info.state = VIR_DOMAIN_SHUTOFF;
|
|
|
|
privdom->id = -1;
|
|
|
|
domain->id = -1;
|
|
|
|
} else {
|
|
|
|
privdom->active = 0;
|
|
|
|
}
|
|
|
|
return 0;
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testDomainRestore(virConnectPtr conn,
|
|
|
|
const char *path)
|
2006-06-06 03:32:51 +00:00
|
|
|
{
|
2007-07-27 23:23:00 +00:00
|
|
|
char *xml;
|
|
|
|
char magic[15];
|
|
|
|
int fd, len, ret, domid;
|
|
|
|
GET_CONNECTION(conn, -1);
|
|
|
|
|
|
|
|
if ((fd = open(path, O_RDONLY)) < 0) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-03-27 14:01:59 +00:00
|
|
|
_("cannot read domain image"));
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
2007-07-27 23:23:00 +00:00
|
|
|
if (read(fd, magic, sizeof(magic)) != sizeof(magic)) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-03-27 14:01:59 +00:00
|
|
|
_("incomplete save header"));
|
2007-07-27 23:23:00 +00:00
|
|
|
close(fd);
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
2007-07-27 23:23:00 +00:00
|
|
|
if (memcmp(magic, TEST_SAVE_MAGIC, sizeof(magic))) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-03-27 14:01:59 +00:00
|
|
|
_("mismatched header magic"));
|
2007-07-27 23:23:00 +00:00
|
|
|
close(fd);
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
if (read(fd, (char*)&len, sizeof(len)) != sizeof(len)) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-03-27 14:01:59 +00:00
|
|
|
_("failed to read metadata length"));
|
2007-07-27 23:23:00 +00:00
|
|
|
close(fd);
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
if (len < 1 || len > 8192) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-03-27 14:01:59 +00:00
|
|
|
_("length of metadata out of range"));
|
2007-07-27 23:23:00 +00:00
|
|
|
close(fd);
|
|
|
|
return (-1);
|
|
|
|
}
|
2008-05-29 19:20:22 +00:00
|
|
|
if (VIR_ALLOC_N(xml, len+1) < 0) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "xml");
|
|
|
|
close(fd);
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
if (read(fd, xml, len) != len) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-03-27 14:01:59 +00:00
|
|
|
_("incomplete metdata"));
|
2007-07-27 23:23:00 +00:00
|
|
|
close(fd);
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
xml[len] = '\0';
|
|
|
|
close(fd);
|
|
|
|
domid = privconn->nextDomID++;
|
|
|
|
ret = testLoadDomainFromDoc(conn, domid, xml);
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(xml);
|
2007-07-27 23:23:00 +00:00
|
|
|
return ret < 0 ? -1 : 0;
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testDomainCoreDump(virDomainPtr domain,
|
|
|
|
const char *to,
|
|
|
|
int flags ATTRIBUTE_UNUSED)
|
2006-08-16 16:36:39 +00:00
|
|
|
{
|
2007-07-27 23:23:00 +00:00
|
|
|
int fd;
|
|
|
|
GET_DOMAIN(domain, -1);
|
|
|
|
|
|
|
|
if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
|
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-03-27 14:01:59 +00:00
|
|
|
_("cannot save domain core"));
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
Use safewrite in place of write, in many cases.
Also add "make syntax-check" rules to ensure no new uses sneak in.
There are many uses of write like this:
if (write (fd, xml, towrite) != towrite)
return -1;
The problem is that the syscall can succeed, yet write less than
the requested number of bytes, so the caller should retry
rather than simply failing.
This patch changes most of them to use util.c's safewrite wrapper,
which encapsulates the process. Also, there were a few cases in
which the retry loop was open-coded, and I replaced those, too.
* Makefile.maint (sc_avoid_write): New rule, to avoid recurrence.
* .x-sc_avoid_write: New file. Record two legitimate exemptions.
* qemud/qemud.c (sig_handler, qemudClientWriteBuf): Use safewrite, not write.
* src/conf.c (__virConfWriteFile): Likewise.
* src/qemu_conf.c (qemudSaveConfig, qemudSaveNetworkConfig): Likewise.
* src/qemu_driver.c (qemudWaitForMonitor, qemudStartVMDaemon)
(qemudVMData, PROC_IP_FORWARD): Likewise.
* proxy/libvirt_proxy.c: Include "util.h".
(proxyWriteClientSocket): Use safewrite.
* src/test.c (testDomainSave, testDomainCoreDump): Likewise.
* src/proxy_internal.c (virProxyWriteClientSocket): Likewise.
* src/virsh.c: Include "util-lib.h".
(vshOutputLogFile): Use safewrite.
* src/console.c: Include "util-lib.h".
(vshRunConsole): Use safewrite.
2008-02-22 15:55:04 +00:00
|
|
|
if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-03-27 14:01:59 +00:00
|
|
|
_("cannot write header"));
|
2007-07-27 23:23:00 +00:00
|
|
|
close(fd);
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
2007-07-27 23:23:00 +00:00
|
|
|
if (close(fd) < 0) {
|
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-03-27 14:01:59 +00:00
|
|
|
_("cannot save domain data"));
|
2007-07-27 23:23:00 +00:00
|
|
|
close(fd);
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
2007-07-27 23:23:00 +00:00
|
|
|
if (privdom->config) {
|
|
|
|
privdom->info.state = VIR_DOMAIN_SHUTOFF;
|
|
|
|
privdom->id = -1;
|
|
|
|
domain->id = -1;
|
|
|
|
} else {
|
|
|
|
privdom->active = 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *testGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) {
|
|
|
|
return strdup("linux");
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned long testGetMaxMemory(virDomainPtr domain) {
|
|
|
|
GET_DOMAIN(domain, -1);
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
return privdom->info.maxMem;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int testSetMaxMemory(virDomainPtr domain,
|
|
|
|
unsigned long memory)
|
|
|
|
{
|
|
|
|
GET_DOMAIN(domain, -1);
|
|
|
|
|
|
|
|
/* XXX validate not over host memory wrt to other domains */
|
|
|
|
privdom->info.maxMem = memory;
|
2007-01-18 21:08:21 +00:00
|
|
|
return (0);
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testSetMemory(virDomainPtr domain,
|
|
|
|
unsigned long memory)
|
|
|
|
{
|
|
|
|
GET_DOMAIN(domain, -1);
|
2007-04-04 14:19:49 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
if (memory > privdom->info.maxMem) {
|
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
privdom->info.memory = memory;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int testSetVcpus(virDomainPtr domain,
|
|
|
|
unsigned int nrCpus) {
|
|
|
|
GET_DOMAIN(domain, -1);
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
/* We allow more cpus in guest than host */
|
|
|
|
if (nrCpus > 32) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
privdom->info.nrVirtCpu = nrCpus;
|
2007-01-18 21:08:21 +00:00
|
|
|
return (0);
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static char *testDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED)
|
2006-08-16 16:36:39 +00:00
|
|
|
{
|
2008-04-28 15:14:59 +00:00
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
2007-01-18 21:08:21 +00:00
|
|
|
unsigned char *uuid;
|
2007-08-09 20:19:12 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_DOMAIN(domain, NULL);
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferVSprintf(&buf, "<domain type='test' id='%d'>\n", domain->id);
|
|
|
|
virBufferVSprintf(&buf, " <name>%s</name>\n", domain->name);
|
2007-01-18 21:08:21 +00:00
|
|
|
uuid = domain->uuid;
|
2007-08-09 20:19:12 +00:00
|
|
|
virUUIDFormat(uuid, uuidstr);
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr);
|
|
|
|
virBufferVSprintf(&buf, " <memory>%lu</memory>\n", privdom->info.maxMem);
|
|
|
|
virBufferVSprintf(&buf, " <vcpu>%d</vcpu>\n", privdom->info.nrVirtCpu);
|
|
|
|
virBufferVSprintf(&buf, " <on_reboot>%s</on_reboot>\n", testRestartFlagToString(privdom->onReboot));
|
|
|
|
virBufferVSprintf(&buf, " <on_poweroff>%s</on_poweroff>\n", testRestartFlagToString(privdom->onPoweroff));
|
|
|
|
virBufferVSprintf(&buf, " <on_crash>%s</on_crash>\n", testRestartFlagToString(privdom->onCrash));
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferAddLit(&buf, "</domain>\n");
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2008-04-28 15:14:59 +00:00
|
|
|
if (virBufferError(&buf)) {
|
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_NO_MEMORY, __FUNCTION__);
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2008-04-28 15:14:59 +00:00
|
|
|
return virBufferContentAndReset(&buf);
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testNumOfDefinedDomains(virConnectPtr conn) {
|
2007-01-18 21:08:21 +00:00
|
|
|
int numInactive = 0, i;
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_CONNECTION(conn, -1);
|
|
|
|
|
2007-01-18 21:08:21 +00:00
|
|
|
for (i = 0 ; i < MAX_DOMAINS ; i++) {
|
2007-07-27 23:23:00 +00:00
|
|
|
if (!privconn->domains[i].active ||
|
|
|
|
privconn->domains[i].info.state != VIR_DOMAIN_SHUTOFF)
|
2007-01-18 21:08:21 +00:00
|
|
|
continue;
|
|
|
|
numInactive++;
|
|
|
|
}
|
|
|
|
return (numInactive);
|
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testListDefinedDomains(virConnectPtr conn,
|
|
|
|
char **const names,
|
|
|
|
int maxnames) {
|
2007-01-18 21:08:21 +00:00
|
|
|
int n = 0, i;
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_CONNECTION(conn, -1);
|
2007-01-18 21:08:21 +00:00
|
|
|
|
|
|
|
for (i = 0, n = 0 ; i < MAX_DOMAINS && n < maxnames ; i++) {
|
2007-07-27 23:23:00 +00:00
|
|
|
if (privconn->domains[i].active &&
|
|
|
|
privconn->domains[i].info.state == VIR_DOMAIN_SHUTOFF) {
|
|
|
|
names[n++] = strdup(privconn->domains[i].name);
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return (n);
|
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static virDomainPtr testDomainDefineXML(virConnectPtr conn,
|
|
|
|
const char *doc) {
|
|
|
|
int handle;
|
2007-01-18 21:08:21 +00:00
|
|
|
xmlDocPtr xml;
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_CONNECTION(conn, NULL);
|
2007-01-18 21:08:21 +00:00
|
|
|
|
|
|
|
if (!(xml = xmlReadDoc(BAD_CAST doc, "domain.xml", NULL,
|
|
|
|
XML_PARSE_NOENT | XML_PARSE_NONET |
|
|
|
|
XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain"));
|
2007-01-18 21:08:21 +00:00
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
handle = testLoadDomain(conn, -1, xml);
|
|
|
|
privconn->domains[handle].config = 1;
|
2007-01-18 21:08:21 +00:00
|
|
|
|
|
|
|
xmlFreeDoc(xml);
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
if (handle < 0)
|
2007-01-18 21:08:21 +00:00
|
|
|
return (NULL);
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
return virGetDomain(conn, privconn->domains[handle].name, privconn->domains[handle].uuid);
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
|
|
|
|
2008-04-04 07:31:24 +00:00
|
|
|
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
|
|
|
|
unsigned long long *freemems,
|
|
|
|
int startCell, int maxCells) {
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
GET_CONNECTION(conn, -1);
|
|
|
|
|
|
|
|
if (startCell > privconn->numCells) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INVALID_ARG,
|
|
|
|
_("Range exceeds available cells"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = startCell, j = 0;
|
|
|
|
(i < privconn->numCells && j < maxCells) ;
|
|
|
|
++i, ++j) {
|
|
|
|
freemems[j] = privconn->cells[i].mem;
|
|
|
|
}
|
|
|
|
|
|
|
|
return j;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testDomainCreate(virDomainPtr domain) {
|
|
|
|
GET_DOMAIN(domain, -1);
|
2007-04-04 14:19:49 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
if (privdom->info.state != VIR_DOMAIN_SHUTOFF) {
|
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Domain is already running"));
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
domain->id = privdom->id = privconn->nextDomID++;
|
|
|
|
privdom->info.state = VIR_DOMAIN_RUNNING;
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int testDomainUndefine(virDomainPtr domain) {
|
|
|
|
GET_DOMAIN(domain, -1);
|
|
|
|
|
|
|
|
if (privdom->info.state != VIR_DOMAIN_SHUTOFF) {
|
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Domain is still running"));
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
privdom->active = 0;
|
2007-01-18 21:08:21 +00:00
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testDomainGetAutostart(virDomainPtr domain,
|
|
|
|
int *autostart)
|
|
|
|
{
|
|
|
|
GET_DOMAIN(domain, -1);
|
|
|
|
*autostart = privdom->autostart;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int testDomainSetAutostart(virDomainPtr domain,
|
|
|
|
int autostart)
|
|
|
|
{
|
|
|
|
GET_DOMAIN(domain, -1);
|
|
|
|
privdom->autostart = autostart ? 1 : 0;
|
|
|
|
return (0);
|
|
|
|
}
|
2007-04-04 14:19:49 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static char *testDomainGetSchedulerType(virDomainPtr domain,
|
|
|
|
int *nparams)
|
|
|
|
{
|
|
|
|
char *type;
|
|
|
|
*nparams = 1;
|
|
|
|
type = strdup("fair");
|
|
|
|
if (!type) {
|
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_NO_MEMORY, "schedular");
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int testDomainGetSchedulerParams(virDomainPtr domain,
|
|
|
|
virSchedParameterPtr params,
|
|
|
|
int *nparams)
|
|
|
|
{
|
|
|
|
GET_DOMAIN(domain, -1);
|
|
|
|
if (*nparams != 1) {
|
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INVALID_ARG, "nparams");
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
2007-07-27 23:23:00 +00:00
|
|
|
strcpy(params[0].field, "weight");
|
|
|
|
params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT;
|
|
|
|
params[0].value.ui = privdom->weight;
|
|
|
|
return 0;
|
|
|
|
}
|
2007-01-18 21:08:21 +00:00
|
|
|
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testDomainSetSchedulerParams(virDomainPtr domain,
|
|
|
|
virSchedParameterPtr params,
|
|
|
|
int nparams)
|
|
|
|
{
|
|
|
|
GET_DOMAIN(domain, -1);
|
|
|
|
if (nparams != 1) {
|
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INVALID_ARG, "nparams");
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
2007-07-27 23:23:00 +00:00
|
|
|
if (STRNEQ(params[0].field, "weight")) {
|
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INVALID_ARG, "field");
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
if (params[0].type != VIR_DOMAIN_SCHED_FIELD_UINT) {
|
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INVALID_ARG, "type");
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
privdom->weight = params[0].value.ui;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDrvOpenStatus testOpenNetwork(virConnectPtr conn,
|
2007-11-14 11:40:57 +00:00
|
|
|
xmlURIPtr uri ATTRIBUTE_UNUSED,
|
2007-12-05 18:28:05 +00:00
|
|
|
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
2007-07-27 23:23:00 +00:00
|
|
|
int flags ATTRIBUTE_UNUSED) {
|
|
|
|
if (STRNEQ(conn->driver->name, "Test"))
|
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
|
|
|
|
|
|
conn->networkPrivateData = conn->privateData;
|
|
|
|
return VIR_DRV_OPEN_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int testCloseNetwork(virConnectPtr conn) {
|
|
|
|
conn->networkPrivateData = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static virNetworkPtr testLookupNetworkByUUID(virConnectPtr conn,
|
|
|
|
const unsigned char *uuid)
|
|
|
|
{
|
|
|
|
int i, idx = -1;
|
|
|
|
GET_CONNECTION(conn, NULL);
|
|
|
|
|
|
|
|
for (i = 0 ; i < MAX_NETWORKS ; i++) {
|
|
|
|
if (privconn->networks[i].active &&
|
|
|
|
memcmp(uuid, privconn->networks[i].uuid, VIR_UUID_BUFLEN) == 0) {
|
|
|
|
idx = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
if (idx < 0) {
|
|
|
|
testError (conn, NULL, NULL, VIR_ERR_NO_NETWORK, NULL);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return virGetNetwork(conn, privconn->networks[idx].name, privconn->networks[idx].uuid);
|
|
|
|
}
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static virNetworkPtr testLookupNetworkByName(virConnectPtr conn,
|
|
|
|
const char *name)
|
|
|
|
{
|
|
|
|
int i, idx = -1;
|
|
|
|
GET_CONNECTION(conn, NULL);
|
|
|
|
|
|
|
|
for (i = 0 ; i < MAX_NETWORKS ; i++) {
|
|
|
|
if (privconn->networks[i].active &&
|
2008-05-14 19:51:24 +00:00
|
|
|
STREQ(name, privconn->networks[i].name)) {
|
2007-07-27 23:23:00 +00:00
|
|
|
idx = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (idx < 0) {
|
|
|
|
testError (conn, NULL, NULL, VIR_ERR_NO_NETWORK, NULL);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return virGetNetwork(conn, privconn->networks[idx].name, privconn->networks[idx].uuid);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int testNumNetworks(virConnectPtr conn) {
|
|
|
|
int numInactive = 0, i;
|
|
|
|
GET_CONNECTION(conn, -1);
|
|
|
|
|
|
|
|
for (i = 0 ; i < MAX_NETWORKS ; i++) {
|
|
|
|
if (!privconn->networks[i].active ||
|
|
|
|
!privconn->networks[i].running)
|
|
|
|
continue;
|
|
|
|
numInactive++;
|
|
|
|
}
|
|
|
|
return (numInactive);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int testListNetworks(virConnectPtr conn, char **const names, int nnames) {
|
|
|
|
int n = 0, i;
|
|
|
|
GET_CONNECTION(conn, -1);
|
|
|
|
|
|
|
|
for (i = 0, n = 0 ; i < MAX_NETWORKS && n < nnames ; i++) {
|
|
|
|
if (privconn->networks[i].active &&
|
|
|
|
privconn->networks[i].running) {
|
|
|
|
names[n++] = strdup(privconn->networks[i].name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (n);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int testNumDefinedNetworks(virConnectPtr conn) {
|
|
|
|
int numInactive = 0, i;
|
|
|
|
GET_CONNECTION(conn, -1);
|
|
|
|
|
|
|
|
for (i = 0 ; i < MAX_NETWORKS ; i++) {
|
|
|
|
if (!privconn->networks[i].active ||
|
|
|
|
privconn->networks[i].running)
|
|
|
|
continue;
|
|
|
|
numInactive++;
|
|
|
|
}
|
|
|
|
return (numInactive);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int testListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
|
|
|
|
int n = 0, i;
|
|
|
|
GET_CONNECTION(conn, -1);
|
|
|
|
|
|
|
|
for (i = 0, n = 0 ; i < MAX_NETWORKS && n < nnames ; i++) {
|
|
|
|
if (privconn->networks[i].active &&
|
|
|
|
!privconn->networks[i].running) {
|
|
|
|
names[n++] = strdup(privconn->networks[i].name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (n);
|
|
|
|
}
|
|
|
|
|
|
|
|
static virNetworkPtr testNetworkCreate(virConnectPtr conn, const char *xml) {
|
|
|
|
int handle = -1;
|
|
|
|
virNetworkPtr net;
|
|
|
|
GET_CONNECTION(conn, NULL);
|
|
|
|
|
|
|
|
if (xml == NULL) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (privconn->numNetworks == MAX_NETWORKS) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("too many networks"));
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((handle = testLoadNetworkFromDoc(conn, xml)) < 0)
|
|
|
|
return (NULL);
|
|
|
|
privconn->networks[handle].config = 0;
|
|
|
|
|
|
|
|
net = virGetNetwork(conn, privconn->networks[handle].name, privconn->networks[handle].uuid);
|
|
|
|
if (net == NULL) return NULL;
|
|
|
|
privconn->numNetworks++;
|
|
|
|
return (net);
|
|
|
|
}
|
|
|
|
|
|
|
|
static virNetworkPtr testNetworkDefine(virConnectPtr conn, const char *xml) {
|
|
|
|
int handle = -1;
|
|
|
|
virNetworkPtr net;
|
|
|
|
GET_CONNECTION(conn, NULL);
|
|
|
|
|
|
|
|
if (xml == NULL) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (privconn->numNetworks == MAX_NETWORKS) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("too many networks"));
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((handle = testLoadNetworkFromDoc(conn, xml)) < 0)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
net = virGetNetwork(conn, privconn->networks[handle].name, privconn->networks[handle].uuid);
|
|
|
|
privconn->networks[handle].config = 1;
|
|
|
|
if (net == NULL) return NULL;
|
|
|
|
privconn->numNetworks++;
|
|
|
|
return (net);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int testNetworkUndefine(virNetworkPtr network) {
|
|
|
|
GET_NETWORK(network, -1);
|
|
|
|
|
|
|
|
if (privnet->running) {
|
|
|
|
testError(network->conn, NULL, network, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Network is still running"));
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
privnet->active = 0;
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int testNetworkStart(virNetworkPtr network) {
|
|
|
|
GET_NETWORK(network, -1);
|
|
|
|
|
|
|
|
if (privnet->running) {
|
|
|
|
testError(network->conn, NULL, network, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Network is already running"));
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
privnet->running = 1;
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int testNetworkDestroy(virNetworkPtr network) {
|
|
|
|
GET_NETWORK(network, -1);
|
|
|
|
|
|
|
|
if (privnet->config) {
|
|
|
|
privnet->running = 0;
|
|
|
|
} else {
|
|
|
|
privnet->active = 0;
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *testNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) {
|
2008-04-28 15:14:59 +00:00
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
2007-07-27 23:23:00 +00:00
|
|
|
unsigned char *uuid;
|
2007-08-09 20:19:12 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_NETWORK(network, NULL);
|
|
|
|
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferAddLit(&buf, "<network>\n");
|
|
|
|
virBufferVSprintf(&buf, " <name>%s</name>\n", network->name);
|
2007-07-27 23:23:00 +00:00
|
|
|
uuid = network->uuid;
|
2007-08-09 20:19:12 +00:00
|
|
|
virUUIDFormat(uuid, uuidstr);
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr);
|
|
|
|
virBufferVSprintf(&buf, " <bridge name='%s'/>\n", privnet->bridge);
|
2007-07-27 23:23:00 +00:00
|
|
|
if (privnet->forward) {
|
|
|
|
if (privnet->forwardDev[0])
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferVSprintf(&buf, " <forward dev='%s'/>\n", privnet->forwardDev);
|
2007-07-27 23:23:00 +00:00
|
|
|
else
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferAddLit(&buf, " <forward/>\n");
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
|
|
|
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferVSprintf(&buf, " <ip address='%s' netmask='%s'>\n",
|
2007-07-27 23:23:00 +00:00
|
|
|
privnet->ipAddress, privnet->ipNetmask);
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferAddLit(&buf, " <dhcp>\n");
|
|
|
|
virBufferVSprintf(&buf, " <range start='%s' end='%s'/>\n",
|
2007-07-27 23:23:00 +00:00
|
|
|
privnet->dhcpStart, privnet->dhcpEnd);
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferAddLit(&buf, " </dhcp>\n");
|
|
|
|
virBufferAddLit(&buf, " </ip>\n");
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferAddLit(&buf, "</network>\n");
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-04-28 15:14:59 +00:00
|
|
|
if (virBufferError(&buf)) {
|
|
|
|
testError(network->conn, NULL, network, VIR_ERR_NO_MEMORY, __FUNCTION__);
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-04-28 15:14:59 +00:00
|
|
|
return virBufferContentAndReset(&buf);
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *testNetworkGetBridgeName(virNetworkPtr network) {
|
|
|
|
char *bridge;
|
|
|
|
GET_NETWORK(network, NULL);
|
|
|
|
bridge = strdup(privnet->bridge);
|
|
|
|
if (!bridge) {
|
|
|
|
testError(network->conn, NULL, network, VIR_ERR_NO_MEMORY, "network");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return bridge;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int testNetworkGetAutostart(virNetworkPtr network,
|
|
|
|
int *autostart) {
|
|
|
|
GET_NETWORK(network, -1);
|
|
|
|
*autostart = privnet->autostart;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int testNetworkSetAutostart(virNetworkPtr network,
|
|
|
|
int autostart) {
|
|
|
|
GET_NETWORK(network, -1);
|
|
|
|
privnet->autostart = autostart ? 1 : 0;
|
2007-01-18 21:08:21 +00:00
|
|
|
return (0);
|
|
|
|
}
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-02-20 15:53:34 +00:00
|
|
|
static virDrvOpenStatus testStorageOpen(virConnectPtr conn,
|
|
|
|
xmlURIPtr uri ATTRIBUTE_UNUSED,
|
|
|
|
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
|
|
|
int flags ATTRIBUTE_UNUSED) {
|
|
|
|
if (STRNEQ(conn->driver->name, "Test"))
|
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
|
|
|
|
|
|
conn->storagePrivateData = conn->privateData;
|
|
|
|
return VIR_DRV_OPEN_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int testStorageClose(virConnectPtr conn) {
|
|
|
|
conn->storagePrivateData = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
|
|
|
|
static virDriver testDriver = {
|
|
|
|
VIR_DRV_TEST,
|
|
|
|
"Test",
|
|
|
|
LIBVIR_VERSION_NUMBER,
|
2008-02-26 07:05:18 +00:00
|
|
|
NULL, /* probe */
|
2007-07-27 23:23:00 +00:00
|
|
|
testOpen, /* open */
|
|
|
|
testClose, /* close */
|
2007-08-21 09:03:55 +00:00
|
|
|
NULL, /* supports_feature */
|
2007-07-27 23:23:00 +00:00
|
|
|
NULL, /* type */
|
|
|
|
testGetVersion, /* version */
|
|
|
|
testGetHostname, /* hostname */
|
|
|
|
testGetURI, /* URI */
|
|
|
|
testGetMaxVCPUs, /* getMaxVcpus */
|
|
|
|
testNodeGetInfo, /* nodeGetInfo */
|
|
|
|
testGetCapabilities, /* getCapabilities */
|
|
|
|
testListDomains, /* listDomains */
|
|
|
|
testNumOfDomains, /* numOfDomains */
|
|
|
|
testDomainCreateLinux, /* domainCreateLinux */
|
|
|
|
testLookupDomainByID, /* domainLookupByID */
|
|
|
|
testLookupDomainByUUID, /* domainLookupByUUID */
|
|
|
|
testLookupDomainByName, /* domainLookupByName */
|
|
|
|
testPauseDomain, /* domainSuspend */
|
|
|
|
testResumeDomain, /* domainResume */
|
|
|
|
testShutdownDomain, /* domainShutdown */
|
|
|
|
testRebootDomain, /* domainReboot */
|
|
|
|
testDestroyDomain, /* domainDestroy */
|
|
|
|
testGetOSType, /* domainGetOSType */
|
|
|
|
testGetMaxMemory, /* domainGetMaxMemory */
|
|
|
|
testSetMaxMemory, /* domainSetMaxMemory */
|
|
|
|
testSetMemory, /* domainSetMemory */
|
|
|
|
testGetDomainInfo, /* domainGetInfo */
|
|
|
|
testDomainSave, /* domainSave */
|
|
|
|
testDomainRestore, /* domainRestore */
|
|
|
|
testDomainCoreDump, /* domainCoreDump */
|
|
|
|
testSetVcpus, /* domainSetVcpus */
|
|
|
|
NULL, /* domainPinVcpu */
|
|
|
|
NULL, /* domainGetVcpus */
|
|
|
|
NULL, /* domainGetMaxVcpus */
|
|
|
|
testDomainDumpXML, /* domainDumpXML */
|
|
|
|
testListDefinedDomains, /* listDefinedDomains */
|
|
|
|
testNumOfDefinedDomains, /* numOfDefinedDomains */
|
|
|
|
testDomainCreate, /* domainCreate */
|
|
|
|
testDomainDefineXML, /* domainDefineXML */
|
|
|
|
testDomainUndefine, /* domainUndefine */
|
|
|
|
NULL, /* domainAttachDevice */
|
|
|
|
NULL, /* domainDetachDevice */
|
|
|
|
testDomainGetAutostart, /* domainGetAutostart */
|
|
|
|
testDomainSetAutostart, /* domainSetAutostart */
|
|
|
|
testDomainGetSchedulerType, /* domainGetSchedulerType */
|
|
|
|
testDomainGetSchedulerParams, /* domainGetSchedulerParameters */
|
|
|
|
testDomainSetSchedulerParams, /* domainSetSchedulerParameters */
|
2007-08-21 09:31:12 +00:00
|
|
|
NULL, /* domainMigratePrepare */
|
|
|
|
NULL, /* domainMigratePerform */
|
|
|
|
NULL, /* domainMigrateFinish */
|
2007-08-21 10:08:12 +00:00
|
|
|
NULL, /* domainBlockStats */
|
|
|
|
NULL, /* domainInterfaceStats */
|
2008-04-04 07:31:24 +00:00
|
|
|
testNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
|
2007-09-30 13:09:07 +00:00
|
|
|
NULL, /* getFreeMemory */
|
2007-07-27 23:23:00 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static virNetworkDriver testNetworkDriver = {
|
|
|
|
"Test",
|
|
|
|
testOpenNetwork, /* open */
|
|
|
|
testCloseNetwork, /* close */
|
|
|
|
testNumNetworks, /* numOfNetworks */
|
|
|
|
testListNetworks, /* listNetworks */
|
|
|
|
testNumDefinedNetworks, /* numOfDefinedNetworks */
|
|
|
|
testListDefinedNetworks, /* listDefinedNetworks */
|
|
|
|
testLookupNetworkByUUID, /* networkLookupByUUID */
|
|
|
|
testLookupNetworkByName, /* networkLookupByName */
|
|
|
|
testNetworkCreate, /* networkCreateXML */
|
|
|
|
testNetworkDefine, /* networkDefineXML */
|
|
|
|
testNetworkUndefine, /* networkUndefine */
|
|
|
|
testNetworkStart, /* networkCreate */
|
|
|
|
testNetworkDestroy, /* networkDestroy */
|
|
|
|
testNetworkDumpXML, /* networkDumpXML */
|
|
|
|
testNetworkGetBridgeName, /* networkGetBridgeName */
|
|
|
|
testNetworkGetAutostart, /* networkGetAutostart */
|
|
|
|
testNetworkSetAutostart, /* networkSetAutostart */
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2008-02-20 15:53:34 +00:00
|
|
|
static virStorageDriver testStorageDriver = {
|
|
|
|
.name = "Test",
|
|
|
|
.open = testStorageOpen,
|
|
|
|
.close = testStorageClose,
|
|
|
|
};
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
/**
|
|
|
|
* testRegister:
|
|
|
|
*
|
|
|
|
* Registers the test driver
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
testRegister(void)
|
|
|
|
{
|
|
|
|
if (virRegisterDriver(&testDriver) < 0)
|
|
|
|
return -1;
|
|
|
|
if (virRegisterNetworkDriver(&testNetworkDriver) < 0)
|
|
|
|
return -1;
|
2008-02-20 15:53:34 +00:00
|
|
|
if (virRegisterStorageDriver(&testStorageDriver) < 0)
|
|
|
|
return -1;
|
2007-07-27 23:23:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-03-15 07:43:16 +00:00
|
|
|
#endif /* WITH_TEST */
|