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 <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 "test.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"
|
2008-07-11 16:39:08 +00:00
|
|
|
#include "network_conf.h"
|
2008-07-11 16:41:27 +00:00
|
|
|
#include "domain_conf.h"
|
|
|
|
#include "xml.h"
|
2007-04-04 14:19:49 +00:00
|
|
|
|
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;
|
2008-07-11 16:41:27 +00:00
|
|
|
virCapsPtr caps;
|
2007-01-18 21:08:21 +00:00
|
|
|
virNodeInfo nodeInfo;
|
2008-07-11 16:41:27 +00:00
|
|
|
virDomainObjPtr domains;
|
2008-07-11 16:39:08 +00:00
|
|
|
virNetworkObjPtr 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
|
2008-07-11 16:41:27 +00:00
|
|
|
#define TEST_EMULATOR "/usr/bin/test-hv"
|
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) \
|
|
|
|
testConnPtr privconn; \
|
2008-07-11 16:41:27 +00:00
|
|
|
virDomainObjPtr privdom; \
|
2007-07-27 23:23:00 +00:00
|
|
|
\
|
|
|
|
privconn = (testConnPtr)dom->conn->privateData; \
|
2008-07-11 16:41:27 +00:00
|
|
|
do { \
|
|
|
|
if ((privdom = virDomainFindByName(privconn->domains, \
|
|
|
|
(dom)->name)) == NULL) { \
|
|
|
|
testError((dom)->conn, (dom), NULL, VIR_ERR_INVALID_ARG, \
|
|
|
|
__FUNCTION__); \
|
|
|
|
return (ret); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
2007-07-27 23:23:00 +00:00
|
|
|
|
|
|
|
#define GET_NETWORK(net, ret) \
|
|
|
|
testConnPtr privconn; \
|
2008-07-11 16:39:08 +00:00
|
|
|
virNetworkObjPtr privnet; \
|
2007-07-27 23:23:00 +00:00
|
|
|
\
|
|
|
|
privconn = (testConnPtr)net->conn->privateData; \
|
2008-07-11 16:39:08 +00:00
|
|
|
do { \
|
|
|
|
if ((privnet = virNetworkFindByName(privconn->networks, \
|
|
|
|
(net)->name)) == NULL) { \
|
|
|
|
testError((net)->conn, NULL, (net), VIR_ERR_INVALID_ARG, \
|
|
|
|
__FUNCTION__); \
|
|
|
|
return (ret); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
#define GET_CONNECTION(conn) \
|
2007-07-27 23:23:00 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
static virCapsPtr
|
|
|
|
testBuildCapabilities(virConnectPtr conn) {
|
|
|
|
virCapsPtr caps;
|
|
|
|
virCapsGuestPtr guest;
|
|
|
|
const char *const guest_types[] = { "hvm", "xen" };
|
|
|
|
int i;
|
|
|
|
GET_CONNECTION(conn);
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
if ((caps = virCapabilitiesNew(TEST_MODEL, 0, 0)) == NULL)
|
|
|
|
goto no_memory;
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
if (virCapabilitiesAddHostFeature(caps, "pae") < 0)
|
|
|
|
goto no_memory;
|
|
|
|
if (virCapabilitiesAddHostFeature(caps ,"nonpae") < 0)
|
|
|
|
goto no_memory;
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2008-07-11 16:41:27 +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;
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
for (i = 0; i < ARRAY_CARDINALITY(guest_types) ; i++) {
|
|
|
|
if ((guest = virCapabilitiesAddGuest(caps,
|
|
|
|
guest_types[i],
|
|
|
|
TEST_MODEL,
|
|
|
|
TEST_MODEL_WORDSIZE,
|
|
|
|
TEST_EMULATOR,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL)) == NULL)
|
|
|
|
goto no_memory;
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
if (virCapabilitiesAddGuestDomain(guest,
|
|
|
|
"test",
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL) == NULL)
|
|
|
|
goto no_memory;
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
if (virCapabilitiesAddGuestFeature(guest, "pae", 1, 1) == NULL)
|
|
|
|
goto no_memory;
|
|
|
|
if (virCapabilitiesAddGuestFeature(guest ,"nonpae", 1, 1) == NULL)
|
|
|
|
goto no_memory;
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
return caps;
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
no_memory:
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
|
|
|
|
virCapabilitiesFree(caps);
|
|
|
|
return NULL;
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
static const char *defaultDomainXML =
|
|
|
|
"<domain type='test'>"
|
|
|
|
" <name>test</name>"
|
|
|
|
" <memory>8388608</memory>"
|
|
|
|
" <currentMemory>2097152</currentMemory>"
|
|
|
|
" <vcpu>2</vcpu>"
|
|
|
|
" <os>"
|
|
|
|
" <type>hvm</type>"
|
|
|
|
" </os>"
|
|
|
|
"</domain>";
|
2007-07-27 23:23:00 +00:00
|
|
|
|
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
static const char *defaultNetworkXML =
|
|
|
|
"<network>"
|
|
|
|
" <name>default</name>"
|
|
|
|
" <bridge name='virbr0' />"
|
|
|
|
" <forward/>"
|
|
|
|
" <ip address='192.168.122.1' netmask='255.255.255.0'>"
|
|
|
|
" <dhcp>"
|
|
|
|
" <range start='192.168.122.2' end='192.168.122.254' />"
|
|
|
|
" </dhcp>"
|
|
|
|
" </ip>"
|
|
|
|
"</network>";
|
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;
|
2008-07-11 16:41:27 +00:00
|
|
|
virDomainDefPtr domdef = NULL;
|
|
|
|
virDomainObjPtr domobj = NULL;
|
|
|
|
virNetworkDefPtr netdef = NULL;
|
|
|
|
virNetworkObjPtr netobj = NULL;
|
2008-07-11 16:39:08 +00:00
|
|
|
|
2008-05-29 19:20:22 +00:00
|
|
|
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;
|
|
|
|
}
|
2008-07-11 16:41:27 +00:00
|
|
|
conn->privateData = privconn;
|
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"));
|
2008-07-11 16:41:27 +00:00
|
|
|
goto 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
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
if (!(privconn->caps = testBuildCapabilities(conn)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
privconn->nextDomID = 1;
|
|
|
|
|
|
|
|
if (!(domdef = virDomainDefParseString(conn, privconn->caps, defaultDomainXML)))
|
|
|
|
goto error;
|
|
|
|
if (!(domobj = virDomainAssignDef(conn, &privconn->domains, domdef))) {
|
|
|
|
virDomainDefFree(domdef);
|
|
|
|
goto error;
|
|
|
|
}
|
2008-07-25 13:27:12 +00:00
|
|
|
domobj->def->id = privconn->nextDomID++;
|
2008-07-11 16:41:27 +00:00
|
|
|
domobj->state = VIR_DOMAIN_RUNNING;
|
|
|
|
domobj->persistent = 1;
|
|
|
|
|
|
|
|
if (!(netdef = virNetworkDefParseString(conn, defaultNetworkXML)))
|
|
|
|
goto error;
|
|
|
|
if (!(netobj = virNetworkAssignDef(conn, &privconn->networks, netdef))) {
|
|
|
|
virNetworkDefFree(netdef);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
netobj->active = 1;
|
|
|
|
netobj->persistent = 1;
|
|
|
|
|
|
|
|
return VIR_DRV_OPEN_SUCCESS;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virDomainObjFree(privconn->domains);
|
|
|
|
virNetworkObjFree(privconn->networks);
|
|
|
|
virCapabilitiesFree(privconn->caps);
|
|
|
|
VIR_FREE(privconn);
|
|
|
|
return VIR_DRV_OPEN_ERROR;
|
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;
|
2008-07-25 09:31:24 +00:00
|
|
|
xmlNodePtr *domains = NULL, *networks = NULL;
|
2007-01-18 21:08:21 +00:00
|
|
|
xmlXPathContextPtr ctxt = NULL;
|
|
|
|
virNodeInfoPtr nodeInfo;
|
2008-07-11 16:41:27 +00:00
|
|
|
virNetworkObjPtr net;
|
|
|
|
virDomainObjPtr dom;
|
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;
|
|
|
|
}
|
2008-07-11 16:41:27 +00:00
|
|
|
conn->privateData = privconn;
|
|
|
|
|
|
|
|
if (!(privconn->caps = testBuildCapabilities(conn)))
|
|
|
|
goto 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
|
|
|
privconn->nextDomID = 1;
|
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++) {
|
2008-07-11 16:41:27 +00:00
|
|
|
virDomainDefPtr def;
|
|
|
|
char *relFile = virXMLPropString(domains[i], "file");
|
|
|
|
if (relFile != NULL) {
|
|
|
|
char *absFile = testBuildFilename(file, relFile);
|
|
|
|
VIR_FREE(relFile);
|
|
|
|
if (!absFile) {
|
|
|
|
testError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("resolving domain filename"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
def = virDomainDefParseFile(conn, privconn->caps, absFile);
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(absFile);
|
2008-07-11 16:41:27 +00:00
|
|
|
if (!def)
|
|
|
|
goto error;
|
|
|
|
} else {
|
|
|
|
if ((def = virDomainDefParseNode(conn, privconn->caps, xml, domains[i])) == NULL)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(dom = virDomainAssignDef(conn, &privconn->domains, def))) {
|
|
|
|
virDomainDefFree(def);
|
2007-01-18 21:08:21 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2008-07-11 16:41:27 +00:00
|
|
|
|
|
|
|
dom->state = VIR_DOMAIN_RUNNING;
|
|
|
|
dom->def->id = privconn->nextDomID++;
|
|
|
|
dom->persistent = 1;
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
2008-07-19 07:42:34 +00:00
|
|
|
if (domains != NULL)
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(domains);
|
2007-07-27 23:23:00 +00:00
|
|
|
|
|
|
|
ret = virXPathNodeSet("/node/network", ctxt, &networks);
|
2008-07-11 16:39:08 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
testError(NULL, NULL, NULL, VIR_ERR_XML_ERROR, _("node network list"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
for (i = 0 ; i < ret ; i++) {
|
|
|
|
virNetworkDefPtr def;
|
|
|
|
char *relFile = virXMLPropString(networks[i], "file");
|
|
|
|
if (relFile != NULL) {
|
|
|
|
char *absFile = testBuildFilename(file, relFile);
|
|
|
|
VIR_FREE(relFile);
|
2007-07-27 23:23:00 +00:00
|
|
|
if (!absFile) {
|
|
|
|
testError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("resolving network filename"));
|
|
|
|
goto error;
|
|
|
|
}
|
2008-07-11 16:39:08 +00:00
|
|
|
|
|
|
|
def = virNetworkDefParseFile(conn, absFile);
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(absFile);
|
2008-07-11 16:39:08 +00:00
|
|
|
if (!def)
|
|
|
|
goto error;
|
|
|
|
} else {
|
|
|
|
if ((def = virNetworkDefParseNode(conn, xml, networks[i])) == NULL)
|
|
|
|
goto error;
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
2008-07-11 16:39:08 +00:00
|
|
|
if (!(net = virNetworkAssignDef(conn, &privconn->networks,
|
|
|
|
def))) {
|
|
|
|
virNetworkDefFree(def);
|
|
|
|
goto error;
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
2008-07-11 16:39:08 +00:00
|
|
|
|
|
|
|
net->persistent = 1;
|
|
|
|
}
|
2008-07-19 07:42:34 +00:00
|
|
|
if (networks != NULL)
|
2008-07-11 16:39:08 +00:00
|
|
|
VIR_FREE(networks);
|
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-07-11 16:41:27 +00:00
|
|
|
xmlFreeDoc(xml);
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(domains);
|
|
|
|
VIR_FREE(networks);
|
2007-01-18 21:08:21 +00:00
|
|
|
if (fd != -1)
|
|
|
|
close(fd);
|
2008-07-11 16:41:27 +00:00
|
|
|
dom = privconn->domains;
|
|
|
|
while (dom) {
|
|
|
|
virDomainObjPtr tmp = dom->next;
|
|
|
|
virDomainObjFree(dom);
|
|
|
|
dom = tmp;
|
|
|
|
}
|
|
|
|
net = privconn->networks;
|
|
|
|
while (net) {
|
|
|
|
virNetworkObjPtr tmp = net->next;
|
|
|
|
virNetworkObjFree(net);
|
|
|
|
net = tmp;
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
2006-06-06 03:32:51 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
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
|
|
|
{
|
2008-07-11 16:41:27 +00:00
|
|
|
virDomainObjPtr dom;
|
|
|
|
virNetworkObjPtr net;
|
|
|
|
GET_CONNECTION(conn);
|
|
|
|
virCapabilitiesFree(privconn->caps);
|
|
|
|
dom = privconn->domains;
|
|
|
|
while (dom) {
|
|
|
|
virDomainObjPtr tmp = dom->next;
|
|
|
|
virDomainObjFree(dom);
|
|
|
|
dom = tmp;
|
|
|
|
}
|
|
|
|
net = privconn->networks;
|
|
|
|
while (net) {
|
|
|
|
virNetworkObjPtr tmp = net->next;
|
|
|
|
virNetworkObjFree(net);
|
|
|
|
net = tmp;
|
|
|
|
}
|
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;
|
2008-07-11 16:41:27 +00:00
|
|
|
GET_CONNECTION(conn);
|
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
|
|
|
{
|
2008-07-11 16:41:27 +00:00
|
|
|
GET_CONNECTION(conn);
|
2007-07-27 23:23:00 +00:00
|
|
|
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
|
|
|
char *xml;
|
2008-07-11 16:41:27 +00:00
|
|
|
GET_CONNECTION(conn);
|
2008-02-27 04:35:08 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL) {
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
|
|
|
|
return NULL;
|
2008-04-08 09:26:24 +00:00
|
|
|
}
|
2008-02-27 04:35:08 +00:00
|
|
|
|
|
|
|
return xml;
|
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
|
|
|
{
|
2008-07-11 16:41:27 +00:00
|
|
|
int numActive = 0;
|
|
|
|
virDomainObjPtr dom;
|
|
|
|
GET_CONNECTION(conn);
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
dom = privconn->domains;
|
|
|
|
while (dom) {
|
|
|
|
if (virDomainIsActive(dom))
|
|
|
|
numActive++;
|
|
|
|
dom = dom->next;
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
2008-07-11 16:41:27 +00:00
|
|
|
return numActive;
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static virDomainPtr
|
2008-07-11 16:41:27 +00:00
|
|
|
testDomainCreateLinux(virConnectPtr conn, const char *xml,
|
2007-01-18 21:08:21 +00:00
|
|
|
unsigned int flags ATTRIBUTE_UNUSED)
|
2006-08-16 16:36:39 +00:00
|
|
|
{
|
2008-07-11 16:41:27 +00:00
|
|
|
virDomainPtr ret;
|
|
|
|
virDomainDefPtr def;
|
|
|
|
virDomainObjPtr dom;
|
|
|
|
GET_CONNECTION(conn);
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
if ((def = virDomainDefParseString(conn, privconn->caps, xml)) == NULL)
|
|
|
|
return NULL;
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
if ((dom = virDomainAssignDef(conn, &privconn->domains,
|
|
|
|
def)) == NULL) {
|
|
|
|
virDomainDefFree(def);
|
|
|
|
return NULL;
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
2008-07-11 16:41:27 +00:00
|
|
|
dom->state = VIR_DOMAIN_RUNNING;
|
|
|
|
dom->def->id = privconn->nextDomID++;
|
2007-04-04 14:19:49 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
ret = virGetDomain(conn, def->name, def->uuid);
|
|
|
|
if (!ret)
|
|
|
|
return NULL;
|
|
|
|
ret->id = def->id;
|
|
|
|
return ret;
|
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
|
|
|
{
|
2008-07-11 16:41:27 +00:00
|
|
|
virDomainObjPtr dom = NULL;
|
|
|
|
virDomainPtr ret;
|
|
|
|
GET_CONNECTION(conn);
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
if ((dom = virDomainFindByID(privconn->domains, id)) == NULL) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError (conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
|
2008-07-11 16:41:27 +00:00
|
|
|
return NULL;
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
|
|
|
|
if (!ret)
|
|
|
|
return NULL;
|
|
|
|
ret->id = dom->def->id;
|
|
|
|
return ret;
|
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
|
|
|
{
|
2008-07-11 16:41:27 +00:00
|
|
|
virDomainPtr ret;
|
|
|
|
virDomainObjPtr dom = NULL;
|
|
|
|
GET_CONNECTION(conn);
|
2007-07-06 14:56:15 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
if ((dom = virDomainFindByUUID(privconn->domains, uuid)) == NULL) {
|
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
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
|
|
|
|
if (!ret)
|
|
|
|
return NULL;
|
|
|
|
ret->id = dom->def->id;
|
|
|
|
return ret;
|
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
|
|
|
{
|
2008-07-11 16:41:27 +00:00
|
|
|
virDomainPtr ret;
|
|
|
|
virDomainObjPtr dom = NULL;
|
|
|
|
GET_CONNECTION(conn);
|
2007-07-06 14:56:15 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
if ((dom = virDomainFindByName(privconn->domains, name)) == NULL) {
|
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
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
|
|
|
|
if (!ret)
|
|
|
|
return NULL;
|
|
|
|
ret->id = dom->def->id;
|
|
|
|
return ret;
|
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
|
|
|
{
|
2008-07-11 16:41:27 +00:00
|
|
|
int n = 0;
|
|
|
|
virDomainObjPtr dom;
|
|
|
|
GET_CONNECTION(conn);
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
dom = privconn->domains;
|
|
|
|
while (dom && n < maxids) {
|
|
|
|
if (virDomainIsActive(dom))
|
|
|
|
ids[n++] = dom->def->id;
|
|
|
|
dom = dom->next;
|
2006-06-06 03:32:51 +00:00
|
|
|
}
|
2008-07-11 16:41:27 +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
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
privdom->state = VIR_DOMAIN_SHUTOFF;
|
2008-07-25 13:27:12 +00:00
|
|
|
privdom->def->id = -1;
|
|
|
|
domain->id = -1;
|
2008-07-11 16:41:27 +00:00
|
|
|
if (!privdom->persistent) {
|
|
|
|
virDomainRemoveInactive(&privconn->domains,
|
|
|
|
privdom);
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
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
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
if (privdom->state != VIR_DOMAIN_PAUSED) {
|
|
|
|
testError(domain->conn, domain, NULL,
|
|
|
|
VIR_ERR_INTERNAL_ERROR, _("domain not paused"));
|
2007-07-27 23:23:00 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2007-04-04 14:19:49 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
privdom->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
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
if (privdom->state == VIR_DOMAIN_SHUTOFF ||
|
|
|
|
privdom->state == VIR_DOMAIN_PAUSED) {
|
|
|
|
testError(domain->conn, domain, NULL,
|
|
|
|
VIR_ERR_INTERNAL_ERROR, _("domain not running"));
|
2007-07-27 23:23:00 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2007-04-04 14:19:49 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
privdom->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
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
if (privdom->state == VIR_DOMAIN_SHUTOFF) {
|
2007-07-27 23:23:00 +00:00
|
|
|
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
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
privdom->state = VIR_DOMAIN_SHUTOFF;
|
2007-01-22 16:25:27 +00:00
|
|
|
domain->id = -1;
|
2008-07-11 16:41:27 +00:00
|
|
|
privdom->def->id = -1;
|
2007-01-18 21:08:21 +00:00
|
|
|
|
|
|
|
return (0);
|
2006-06-14 23:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Similar behaviour as shutdown */
|
2008-07-11 16:41:27 +00:00
|
|
|
static int testRebootDomain (virDomainPtr domain,
|
|
|
|
unsigned int action ATTRIBUTE_UNUSED)
|
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
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
privdom->state = VIR_DOMAIN_SHUTDOWN;
|
|
|
|
switch (privdom->def->onReboot) {
|
|
|
|
case VIR_DOMAIN_LIFECYCLE_DESTROY:
|
|
|
|
privdom->state = VIR_DOMAIN_SHUTOFF;
|
2007-07-27 23:23:00 +00:00
|
|
|
domain->id = -1;
|
2008-07-11 16:41:27 +00:00
|
|
|
privdom->def->id = -1;
|
2007-01-18 21:08:21 +00:00
|
|
|
break;
|
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
case VIR_DOMAIN_LIFECYCLE_RESTART:
|
|
|
|
privdom->state = VIR_DOMAIN_RUNNING;
|
2007-01-18 21:08:21 +00:00
|
|
|
break;
|
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
case VIR_DOMAIN_LIFECYCLE_PRESERVE:
|
|
|
|
privdom->state = VIR_DOMAIN_SHUTOFF;
|
2007-07-27 23:23:00 +00:00
|
|
|
domain->id = -1;
|
2008-07-11 16:41:27 +00:00
|
|
|
privdom->def->id = -1;
|
2007-01-18 21:08:21 +00:00
|
|
|
break;
|
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME:
|
|
|
|
privdom->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:
|
2008-07-11 16:41:27 +00:00
|
|
|
privdom->state = VIR_DOMAIN_SHUTOFF;
|
2007-07-27 23:23:00 +00:00
|
|
|
domain->id = -1;
|
2008-07-11 16:41:27 +00:00
|
|
|
privdom->def->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);
|
|
|
|
}
|
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
info->state = privdom->state;
|
|
|
|
info->memory = privdom->def->memory;
|
|
|
|
info->maxMem = privdom->def->maxmem;
|
|
|
|
info->nrVirtCpu = privdom->def->vcpus;
|
|
|
|
info->cpuTime = ((tv.tv_sec * 1000ll * 1000ll * 1000ll) + (tv.tv_usec * 1000ll));
|
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);
|
|
|
|
}
|
2008-07-11 16:41:27 +00:00
|
|
|
privdom->state = VIR_DOMAIN_SHUTOFF;
|
|
|
|
if (!privdom->persistent) {
|
|
|
|
virDomainRemoveInactive(&privconn->domains,
|
|
|
|
privdom);
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
|
|
|
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];
|
2008-07-11 16:41:27 +00:00
|
|
|
int fd, len;
|
|
|
|
virDomainDefPtr def;
|
|
|
|
virDomainObjPtr dom;
|
|
|
|
GET_CONNECTION(conn);
|
2007-07-27 23:23:00 +00:00
|
|
|
|
|
|
|
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);
|
2008-07-11 16:41:27 +00:00
|
|
|
|
|
|
|
def = virDomainDefParseString(conn, privconn->caps, xml);
|
2008-05-29 19:20:22 +00:00
|
|
|
VIR_FREE(xml);
|
2008-07-11 16:41:27 +00:00
|
|
|
if (!def)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if ((dom = virDomainAssignDef(conn, &privconn->domains,
|
|
|
|
def)) == NULL) {
|
|
|
|
virDomainDefFree(def);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
dom->state = VIR_DOMAIN_RUNNING;
|
|
|
|
dom->def->id = privconn->nextDomID++;
|
|
|
|
return dom->def->id;
|
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);
|
|
|
|
}
|
2008-07-11 16:41:27 +00:00
|
|
|
privdom->state = VIR_DOMAIN_SHUTOFF;
|
|
|
|
if (!privdom->persistent) {
|
|
|
|
virDomainRemoveInactive(&privconn->domains,
|
|
|
|
privdom);
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
static char *testGetOSType(virDomainPtr dom) {
|
|
|
|
char *ret = strdup("linux");
|
|
|
|
if (!ret)
|
|
|
|
testError(dom->conn, dom, NULL, VIR_ERR_NO_MEMORY, NULL);
|
|
|
|
return ret;
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned long testGetMaxMemory(virDomainPtr domain) {
|
|
|
|
GET_DOMAIN(domain, -1);
|
2006-08-16 16:36:39 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
return privdom->def->maxmem;
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int testSetMaxMemory(virDomainPtr domain,
|
|
|
|
unsigned long memory)
|
|
|
|
{
|
|
|
|
GET_DOMAIN(domain, -1);
|
|
|
|
|
|
|
|
/* XXX validate not over host memory wrt to other domains */
|
2008-07-11 16:41:27 +00:00
|
|
|
privdom->def->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
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
if (memory > privdom->def->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
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
privdom->def->memory = memory;
|
2007-07-27 23:23:00 +00:00
|
|
|
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
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
privdom->def->vcpus = nrCpus;
|
2007-01-18 21:08:21 +00:00
|
|
|
return (0);
|
2006-08-16 16:36:39 +00:00
|
|
|
}
|
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
static char *testDomainDumpXML(virDomainPtr domain, int flags)
|
2006-08-16 16:36:39 +00:00
|
|
|
{
|
2008-07-11 16:41:27 +00:00
|
|
|
virDomainDefPtr def;
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_DOMAIN(domain, NULL);
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
|
|
|
|
privdom->newDef ? privdom->newDef : privdom->def;
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
return virDomainDefFormat(domain->conn,
|
|
|
|
def,
|
|
|
|
flags);
|
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) {
|
2008-07-11 16:41:27 +00:00
|
|
|
int numInactive = 0;
|
|
|
|
virDomainObjPtr dom;
|
|
|
|
GET_CONNECTION(conn);
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
dom = privconn->domains;
|
|
|
|
while (dom) {
|
|
|
|
if (!virDomainIsActive(dom))
|
|
|
|
numInactive++;
|
|
|
|
dom = dom->next;
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
2008-07-11 16:41:27 +00:00
|
|
|
return numInactive;
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static int testListDefinedDomains(virConnectPtr conn,
|
|
|
|
char **const names,
|
|
|
|
int maxnames) {
|
2008-07-11 16:41:27 +00:00
|
|
|
int n = 0;
|
|
|
|
virDomainObjPtr dom;
|
|
|
|
GET_CONNECTION(conn);
|
|
|
|
|
|
|
|
dom = privconn->domains;
|
|
|
|
memset(names, 0, sizeof(*names)*maxnames);
|
|
|
|
while (dom && n < maxnames) {
|
2008-07-25 13:27:12 +00:00
|
|
|
if (!virDomainIsActive(dom) &&
|
2008-07-11 16:41:27 +00:00
|
|
|
!(names[n++] = strdup(dom->def->name)))
|
|
|
|
goto no_memory;
|
|
|
|
dom = dom->next;
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
2008-07-11 16:41:27 +00:00
|
|
|
return n;
|
|
|
|
|
|
|
|
no_memory:
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
|
|
|
|
for (n = 0 ; n < maxnames ; n++)
|
|
|
|
VIR_FREE(names[n]);
|
|
|
|
return -1;
|
2007-01-18 21:08:21 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static virDomainPtr testDomainDefineXML(virConnectPtr conn,
|
2008-07-11 16:41:27 +00:00
|
|
|
const char *xml) {
|
|
|
|
virDomainPtr ret;
|
|
|
|
virDomainDefPtr def;
|
|
|
|
virDomainObjPtr dom;
|
|
|
|
GET_CONNECTION(conn);
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
if ((def = virDomainDefParseString(conn, privconn->caps, xml)) == NULL)
|
|
|
|
return NULL;
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
if ((dom = virDomainAssignDef(conn, &privconn->domains,
|
|
|
|
def)) == NULL) {
|
|
|
|
virDomainDefFree(def);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
dom->persistent = 1;
|
|
|
|
dom->def->id = -1;
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
ret = virGetDomain(conn, def->name, def->uuid);
|
|
|
|
if (!ret)
|
|
|
|
return NULL;
|
|
|
|
ret->id = -1;
|
|
|
|
return ret;
|
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;
|
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
GET_CONNECTION(conn);
|
2008-04-04 07:31:24 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
if (privdom->state != VIR_DOMAIN_SHUTOFF) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Domain is already running"));
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
domain->id = privdom->def->id = privconn->nextDomID++;
|
|
|
|
privdom->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);
|
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
if (privdom->state != VIR_DOMAIN_SHUTOFF) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Domain is still running"));
|
2007-01-18 21:08:21 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
2008-07-11 16:41:27 +00:00
|
|
|
privdom->state = VIR_DOMAIN_SHUTOFF;
|
|
|
|
virDomainRemoveInactive(&privconn->domains,
|
|
|
|
privdom);
|
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;
|
2008-07-11 16:41:27 +00:00
|
|
|
/* XXX */
|
|
|
|
/*params[0].value.ui = privdom->weight;*/
|
|
|
|
params[0].value.ui = 50;
|
2007-07-27 23:23:00 +00:00
|
|
|
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);
|
|
|
|
}
|
2008-07-11 16:41:27 +00:00
|
|
|
/* XXX */
|
|
|
|
/*privdom->weight = params[0].value.ui;*/
|
2007-07-27 23:23:00 +00:00
|
|
|
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)
|
|
|
|
{
|
2008-07-11 16:39:08 +00:00
|
|
|
virNetworkObjPtr net = NULL;
|
2008-07-11 16:41:27 +00:00
|
|
|
GET_CONNECTION(conn);
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
if ((net = virNetworkFindByUUID(privconn->networks, uuid)) == NULL) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError (conn, NULL, NULL, VIR_ERR_NO_NETWORK, NULL);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
return virGetNetwork(conn, net->def->name, net->def->uuid);
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
2007-01-18 21:08:21 +00:00
|
|
|
|
2007-07-27 23:23:00 +00:00
|
|
|
static virNetworkPtr testLookupNetworkByName(virConnectPtr conn,
|
2008-07-11 16:39:08 +00:00
|
|
|
const char *name)
|
2007-07-27 23:23:00 +00:00
|
|
|
{
|
2008-07-11 16:39:08 +00:00
|
|
|
virNetworkObjPtr net = NULL;
|
2008-07-11 16:41:27 +00:00
|
|
|
GET_CONNECTION(conn);
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
if ((net = virNetworkFindByName(privconn->networks, name)) == NULL) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError (conn, NULL, NULL, VIR_ERR_NO_NETWORK, NULL);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
return virGetNetwork(conn, net->def->name, net->def->uuid);
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int testNumNetworks(virConnectPtr conn) {
|
2008-07-11 16:39:08 +00:00
|
|
|
int numActive = 0;
|
|
|
|
virNetworkObjPtr net;
|
2008-07-11 16:41:27 +00:00
|
|
|
GET_CONNECTION(conn);
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
net = privconn->networks;
|
|
|
|
while (net) {
|
|
|
|
if (virNetworkIsActive(net))
|
|
|
|
numActive++;
|
|
|
|
net = net->next;
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
2008-07-11 16:39:08 +00:00
|
|
|
return numActive;
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int testListNetworks(virConnectPtr conn, char **const names, int nnames) {
|
2008-07-11 16:39:08 +00:00
|
|
|
int n = 0;
|
|
|
|
virNetworkObjPtr net;
|
2008-07-11 16:41:27 +00:00
|
|
|
GET_CONNECTION(conn);
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
net = privconn->networks;
|
|
|
|
memset(names, 0, sizeof(*names)*nnames);
|
|
|
|
while (net && n < nnames) {
|
|
|
|
if (virNetworkIsActive(net) &&
|
|
|
|
!(names[n++] = strdup(net->def->name)))
|
|
|
|
goto no_memory;
|
|
|
|
net = net->next;
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
2008-07-11 16:39:08 +00:00
|
|
|
return n;
|
|
|
|
|
|
|
|
no_memory:
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
|
|
|
|
for (n = 0 ; n < nnames ; n++)
|
|
|
|
VIR_FREE(names[n]);
|
|
|
|
return (-1);
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int testNumDefinedNetworks(virConnectPtr conn) {
|
2008-07-11 16:39:08 +00:00
|
|
|
int numInactive = 0;
|
|
|
|
virNetworkObjPtr net;
|
2008-07-11 16:41:27 +00:00
|
|
|
GET_CONNECTION(conn);
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
net = privconn->networks;
|
|
|
|
while (net) {
|
|
|
|
if (!virNetworkIsActive(net))
|
|
|
|
numInactive++;
|
|
|
|
net = net->next;
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
2008-07-11 16:39:08 +00:00
|
|
|
return numInactive;
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int testListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
|
2008-07-11 16:39:08 +00:00
|
|
|
int n = 0;
|
|
|
|
virNetworkObjPtr net;
|
2008-07-11 16:41:27 +00:00
|
|
|
GET_CONNECTION(conn);
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
net = privconn->networks;
|
|
|
|
memset(names, 0, sizeof(*names)*nnames);
|
|
|
|
while (net && n < nnames) {
|
|
|
|
if (!virNetworkIsActive(net) &&
|
|
|
|
!(names[n++] = strdup(net->def->name)))
|
|
|
|
goto no_memory;
|
|
|
|
net = net->next;
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
2008-07-11 16:39:08 +00:00
|
|
|
return n;
|
|
|
|
|
|
|
|
no_memory:
|
|
|
|
testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
|
|
|
|
for (n = 0 ; n < nnames ; n++)
|
|
|
|
VIR_FREE(names[n]);
|
|
|
|
return (-1);
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static virNetworkPtr testNetworkCreate(virConnectPtr conn, const char *xml) {
|
2008-07-11 16:39:08 +00:00
|
|
|
virNetworkDefPtr def;
|
|
|
|
virNetworkObjPtr net;
|
2008-07-11 16:41:27 +00:00
|
|
|
GET_CONNECTION(conn);
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
if ((def = virNetworkDefParseString(conn, xml)) == NULL)
|
|
|
|
return NULL;
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
if ((net = virNetworkAssignDef(conn, &privconn->networks,
|
|
|
|
def)) == NULL) {
|
|
|
|
virNetworkDefFree(def);
|
|
|
|
return NULL;
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
2008-07-11 16:39:08 +00:00
|
|
|
net->active = 1;
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
return virGetNetwork(conn, def->name, def->uuid);
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static virNetworkPtr testNetworkDefine(virConnectPtr conn, const char *xml) {
|
2008-07-11 16:39:08 +00:00
|
|
|
virNetworkDefPtr def;
|
|
|
|
virNetworkObjPtr net;
|
2008-07-11 16:41:27 +00:00
|
|
|
GET_CONNECTION(conn);
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
if ((def = virNetworkDefParseString(conn, xml)) == NULL)
|
|
|
|
return NULL;
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
if ((net = virNetworkAssignDef(conn, &privconn->networks,
|
|
|
|
def)) == NULL) {
|
|
|
|
virNetworkDefFree(def);
|
|
|
|
return NULL;
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
2008-07-11 16:39:08 +00:00
|
|
|
net->persistent = 1;
|
2007-07-27 23:23:00 +00:00
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
return virGetNetwork(conn, def->name, def->uuid);
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int testNetworkUndefine(virNetworkPtr network) {
|
|
|
|
GET_NETWORK(network, -1);
|
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
if (virNetworkIsActive(privnet)) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(network->conn, NULL, network, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Network is still running"));
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
virNetworkRemoveInactive(&privconn->networks,
|
|
|
|
privnet);
|
2007-07-27 23:23:00 +00:00
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int testNetworkStart(virNetworkPtr network) {
|
|
|
|
GET_NETWORK(network, -1);
|
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
if (virNetworkIsActive(privnet)) {
|
2007-07-27 23:23:00 +00:00
|
|
|
testError(network->conn, NULL, network, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Network is already running"));
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
privnet->active = 1;
|
2007-07-27 23:23:00 +00:00
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int testNetworkDestroy(virNetworkPtr network) {
|
|
|
|
GET_NETWORK(network, -1);
|
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
privnet->active = 0;
|
|
|
|
if (!privnet->persistent) {
|
|
|
|
virNetworkRemoveInactive(&privconn->networks,
|
|
|
|
privnet);
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *testNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) {
|
|
|
|
GET_NETWORK(network, NULL);
|
|
|
|
|
2008-07-11 16:39:08 +00:00
|
|
|
return virNetworkDefFormat(network->conn, privnet->def);
|
2007-07-27 23:23:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *testNetworkGetBridgeName(virNetworkPtr network) {
|
2008-07-11 16:39:08 +00:00
|
|
|
char *bridge = NULL;
|
2007-07-27 23:23:00 +00:00
|
|
|
GET_NETWORK(network, NULL);
|
2008-07-11 16:39:08 +00:00
|
|
|
if (privnet->def->bridge &&
|
|
|
|
!(bridge = strdup(privnet->def->bridge))) {
|
2007-07-27 23:23:00 +00:00
|
|
|
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 */
|
virDomainBlockPeek call
* configure.in: Document AC_SYS_LARGEFILE.
* docs/hvsupport.html.in: Document HV support for virDomainBlockPeek.
* include/libvirt/libvirt.h.in, src/driver.h, src/libvirt.c,
src/libvirt_sym.version: Add virDomainBlockPeek infrastructure.
* src/qemu_driver.c, src/test.c: Null versions of this call.
* src/xen_unified.c, src/xend_internal.c, src/xend_internal.h,
src/xm_internal.c, src/xm_internal.h: Xen implementation.
* tests/sexpr2xmldata/sexpr2xml-curmem.xml,
tests/sexpr2xmldata/sexpr2xml-no-source-cdrom.xml: XML output
has been reordered slightly in the Xen driver, but should be
functionally the same.
2008-06-05 13:17:45 +00:00
|
|
|
NULL, /* domainBlockPeek */
|
2008-06-10 10:43:28 +00:00
|
|
|
NULL, /* domainMemoryPeek */
|
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 */
|