test.c 82.4 KB
Newer Older
1 2 3
/*
 * test.c: A "mock" hypervisor for use by application unit tests
 *
4
 * Copyright (C) 2006-2008 Red Hat, Inc.
5
 * Copyright (C) 2006 Daniel P. Berrange
6
 *
7 8 9 10 11 12 13 14 15 16 17 18 19
 * 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
20 21 22 23
 *
 * Daniel Berrange <berrange@redhat.com>
 */

24
#include <config.h>
25

26 27 28
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
29 30
#include <fcntl.h>
#include <unistd.h>
31
#include <sys/stat.h>
C
Cole Robinson 已提交
32
#include <libxml/xmlsave.h>
33

34 35

#include "virterror_internal.h"
36
#include "datatypes.h"
37
#include "test.h"
38
#include "buf.h"
39
#include "util.h"
40
#include "uuid.h"
41
#include "capabilities.h"
42
#include "memory.h"
43
#include "network_conf.h"
44
#include "domain_conf.h"
C
Cole Robinson 已提交
45
#include "storage_conf.h"
46
#include "xml.h"
47

48 49 50 51 52 53 54 55 56 57 58
#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
59

60 61 62
struct _testConn {
    char path[PATH_MAX];
    int nextDomID;
63
    virCapsPtr caps;
64
    virNodeInfo nodeInfo;
65
    virDomainObjList domains;
66
    virNetworkObjList networks;
C
Cole Robinson 已提交
67
    virStoragePoolObjList pools;
68 69
    int numCells;
    testCell cells[MAX_CELLS];
70 71 72
};
typedef struct _testConn testConn;
typedef struct _testConn *testConnPtr;
73

74
#define TEST_MODEL "i686"
75
#define TEST_MODEL_WORDSIZE 32
76
#define TEST_EMULATOR "/usr/bin/test-hv"
77

78
static const virNodeInfo defaultNodeInfo = {
79
    TEST_MODEL,
80 81 82 83 84 85 86
    1024*1024*3, /* 3 GB */
    16,
    1400,
    2,
    2,
    2,
    2,
87 88
};

89

90
#define testError(conn, code, fmt...)                               \
91
        virReportErrorHelper(conn, VIR_FROM_TEST, code, __FILE__, \
92
                               __FUNCTION__, __LINE__, fmt)
93

94 95
static virCapsPtr
testBuildCapabilities(virConnectPtr conn) {
96
    testConnPtr privconn = conn->privateData;
97 98 99 100
    virCapsPtr caps;
    virCapsGuestPtr guest;
    const char *const guest_types[] = { "hvm", "xen" };
    int i;
101

102 103
    if ((caps = virCapabilitiesNew(TEST_MODEL, 0, 0)) == NULL)
        goto no_memory;
104

105 106 107 108
    if (virCapabilitiesAddHostFeature(caps, "pae") < 0)
        goto no_memory;
    if (virCapabilitiesAddHostFeature(caps ,"nonpae") < 0)
        goto no_memory;
109

110 111 112 113
    for (i = 0; i < privconn->numCells; i++) {
        if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].numCpus,
                                           privconn->cells[i].cpus) < 0)
            goto no_memory;
114 115
    }

116 117 118 119 120 121 122 123 124 125
    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;
126

127 128 129 130 131 132 133
        if (virCapabilitiesAddGuestDomain(guest,
                                          "test",
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
            goto no_memory;
134

135 136 137 138
        if (virCapabilitiesAddGuestFeature(guest, "pae", 1, 1) == NULL)
            goto no_memory;
        if (virCapabilitiesAddGuestFeature(guest ,"nonpae", 1, 1) == NULL)
            goto no_memory;
139 140
    }

141
    return caps;
142

143
no_memory:
144
    testError(conn, VIR_ERR_NO_MEMORY, NULL);
145 146
    virCapabilitiesFree(caps);
    return NULL;
147 148
}

149

150 151 152 153 154 155 156 157 158 159
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>";
160 161


162 163 164 165 166 167 168 169 170 171 172
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>";
173

C
Cole Robinson 已提交
174 175 176 177 178 179 180 181 182 183 184 185
static const char *defaultPoolXML =
"<pool type='dir'>"
"  <name>default-pool</name>"
"  <target>"
"    <path>/default-pool</path>"
"  </target>"
"</pool>";

static const unsigned long long defaultPoolCap = (100 * 1024 * 1024 * 1024ul);
static const unsigned long long defaultPoolAlloc = 0;

static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool);
186

187
static int testOpenDefault(virConnectPtr conn) {
188 189
    int u;
    struct timeval tv;
190
    testConnPtr privconn;
191 192 193 194
    virDomainDefPtr domdef = NULL;
    virDomainObjPtr domobj = NULL;
    virNetworkDefPtr netdef = NULL;
    virNetworkObjPtr netobj = NULL;
C
Cole Robinson 已提交
195 196
    virStoragePoolDefPtr pooldef = NULL;
    virStoragePoolObjPtr poolobj = NULL;
197

198
    if (VIR_ALLOC(privconn) < 0) {
199
        testError(conn, VIR_ERR_NO_MEMORY, "testConn");
200 201
        return VIR_DRV_OPEN_ERROR;
    }
202
    conn->privateData = privconn;
203 204

    if (gettimeofday(&tv, NULL) < 0) {
J
Jim Meyering 已提交
205
        testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("getting time of day"));
206
        goto error;
207 208
    }

209
    memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));
210

211 212 213 214 215 216 217 218 219 220
    // 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;
    }

221 222 223 224 225 226 227 228 229 230 231
    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;
    }
232
    domobj->def->id = privconn->nextDomID++;
233 234 235 236 237 238 239 240 241 242 243 244
    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;

C
Cole Robinson 已提交
245 246 247 248 249 250 251 252 253 254 255 256
    if (!(pooldef = virStoragePoolDefParse(conn, defaultPoolXML, NULL)))
        goto error;

    if (!(poolobj = virStoragePoolObjAssignDef(conn, &privconn->pools,
                                               pooldef))) {
        virStoragePoolDefFree(pooldef);
        goto error;
    }
    if (testStoragePoolObjSetDefaults(poolobj) == -1)
        goto error;
    poolobj->active = 1;

257 258 259
    return VIR_DRV_OPEN_SUCCESS;

error:
260
    virDomainObjListFree(&privconn->domains);
261
    virNetworkObjListFree(&privconn->networks);
C
Cole Robinson 已提交
262
    virStoragePoolObjListFree(&privconn->pools);
263 264 265
    virCapabilitiesFree(privconn->caps);
    VIR_FREE(privconn);
    return VIR_DRV_OPEN_ERROR;
266 267 268 269
}


static char *testBuildFilename(const char *relativeTo,
270 271 272 273 274 275 276 277
                               const char *filename) {
    char *offset;
    int baseLen;
    if (!filename || filename[0] == '\0')
        return (NULL);
    if (filename[0] == '/')
        return strdup(filename);

278
    offset = strrchr(relativeTo, '/');
279
    if ((baseLen = (offset-relativeTo+1))) {
280 281 282
        char *absFile;
        if (VIR_ALLOC_N(absFile, baseLen + strlen(filename) + 1) < 0)
            return NULL;
283 284 285 286 287 288 289
        strncpy(absFile, relativeTo, baseLen);
        absFile[baseLen] = '\0';
        strcat(absFile, filename);
        return absFile;
    } else {
        return strdup(filename);
    }
290 291 292
}

static int testOpenFromFile(virConnectPtr conn,
293
                            const char *file) {
294
    int fd = -1, i, ret;
295 296
    long l;
    char *str;
297
    xmlDocPtr xml = NULL;
298
    xmlNodePtr root = NULL;
C
Cole Robinson 已提交
299
    xmlNodePtr *domains = NULL, *networks = NULL, *pools = NULL;
300 301
    xmlXPathContextPtr ctxt = NULL;
    virNodeInfoPtr nodeInfo;
302 303
    virNetworkObjPtr net;
    virDomainObjPtr dom;
304 305
    testConnPtr privconn;
    if (VIR_ALLOC(privconn) < 0) {
306
        testError(NULL, VIR_ERR_NO_MEMORY, "testConn");
307 308
        return VIR_DRV_OPEN_ERROR;
    }
309 310 311 312
    conn->privateData = privconn;

    if (!(privconn->caps = testBuildCapabilities(conn)))
        goto error;
313 314

    if ((fd = open(file, O_RDONLY)) < 0) {
C
Cole Robinson 已提交
315 316 317
        testError(NULL, VIR_ERR_INTERNAL_ERROR,
                  _("loading host definition file '%s': %s"),
                  file, strerror(errno));
318
        goto error;
319 320
    }

321 322 323
    if (!(xml = xmlReadFd(fd, file, NULL,
                          XML_PARSE_NOENT | XML_PARSE_NONET |
                          XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
J
Jim Meyering 已提交
324
        testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("host"));
325
        goto error;
326
    }
327 328
    close(fd);
    fd = -1;
329

330 331
    root = xmlDocGetRootElement(xml);
    if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "node"))) {
J
Jim Meyering 已提交
332
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node"));
333
        goto error;
334 335
    }

336 337
    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
C
Cole Robinson 已提交
338 339
        testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s",
                  _("creating xpath context"));
340
        goto error;
341
    }
342

343
    privconn->nextDomID = 1;
344
    privconn->numCells = 0;
345 346 347 348 349
    strncpy(privconn->path, file, PATH_MAX-1);
    privconn->path[PATH_MAX-1] = '\0';
    memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));

    nodeInfo = &privconn->nodeInfo;
350
    ret = virXPathLong(conn, "string(/node/cpu/nodes[1])", ctxt, &l);
351 352 353
    if (ret == 0) {
        nodeInfo->nodes = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
354
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu numa nodes"));
355
        goto error;
356
    }
357

358
    ret = virXPathLong(conn, "string(/node/cpu/sockets[1])", ctxt, &l);
359 360 361
    if (ret == 0) {
        nodeInfo->sockets = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
362
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu sockets"));
363
        goto error;
364
    }
365

366
    ret = virXPathLong(conn, "string(/node/cpu/cores[1])", ctxt, &l);
367 368 369
    if (ret == 0) {
        nodeInfo->cores = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
370
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu cores"));
371
        goto error;
372 373
    }

374
    ret = virXPathLong(conn, "string(/node/cpu/threads[1])", ctxt, &l);
375 376 377
    if (ret == 0) {
        nodeInfo->threads = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
378
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu threads"));
379
        goto error;
380
    }
381

382
    nodeInfo->cpus = nodeInfo->cores * nodeInfo->threads * nodeInfo->sockets * nodeInfo->nodes;
383
    ret = virXPathLong(conn, "string(/node/cpu/active[1])", ctxt, &l);
384 385
    if (ret == 0) {
        if (l < nodeInfo->cpus) {
386 387
            nodeInfo->cpus = l;
        }
388
    } else if (ret == -2) {
J
Jim Meyering 已提交
389
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node active cpu"));
390
        goto error;
391
    }
392
    ret = virXPathLong(conn, "string(/node/cpu/mhz[1])", ctxt, &l);
393 394 395
    if (ret == 0) {
        nodeInfo->mhz = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
396
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu mhz"));
397
        goto error;
398 399
    }

400
    str = virXPathString(conn, "string(/node/cpu/model[1])", ctxt);
401 402
    if (str != NULL) {
        strncpy(nodeInfo->model, str, sizeof(nodeInfo->model)-1);
403
        nodeInfo->model[sizeof(nodeInfo->model)-1] = '\0';
404
        VIR_FREE(str);
405 406
    }

407
    ret = virXPathLong(conn, "string(/node/memory[1])", ctxt, &l);
408 409 410
    if (ret == 0) {
        nodeInfo->memory = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
411
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node memory"));
412
        goto error;
413
    }
414

415
    ret = virXPathNodeSet(conn, "/node/domain", ctxt, &domains);
416
    if (ret < 0) {
J
Jim Meyering 已提交
417
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node domain list"));
418
        goto error;
419
    }
420

421
    for (i = 0 ; i < ret ; i++) {
422 423 424 425 426 427
        virDomainDefPtr def;
        char *relFile = virXMLPropString(domains[i], "file");
        if (relFile != NULL) {
            char *absFile = testBuildFilename(file, relFile);
            VIR_FREE(relFile);
            if (!absFile) {
J
Jim Meyering 已提交
428
                testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("resolving domain filename"));
429 430
                goto error;
            }
431 432
            def = virDomainDefParseFile(conn, privconn->caps, absFile,
                                        VIR_DOMAIN_XML_INACTIVE);
433
            VIR_FREE(absFile);
434 435 436
            if (!def)
                goto error;
        } else {
437 438
            if ((def = virDomainDefParseNode(conn, privconn->caps, xml, domains[i],
                                   VIR_DOMAIN_XML_INACTIVE)) == NULL)
439 440 441 442 443
                goto error;
        }

        if (!(dom = virDomainAssignDef(conn, &privconn->domains, def))) {
            virDomainDefFree(def);
444 445
            goto error;
        }
446 447 448 449

        dom->state = VIR_DOMAIN_RUNNING;
        dom->def->id = privconn->nextDomID++;
        dom->persistent = 1;
450
    }
451
    if (domains != NULL)
452
        VIR_FREE(domains);
453

454
    ret = virXPathNodeSet(conn, "/node/network", ctxt, &networks);
455
    if (ret < 0) {
J
Jim Meyering 已提交
456
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node network list"));
457 458 459 460 461 462 463 464
        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);
465
            if (!absFile) {
J
Jim Meyering 已提交
466
                testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("resolving network filename"));
467 468
                goto error;
            }
469 470

            def = virNetworkDefParseFile(conn, absFile);
471
            VIR_FREE(absFile);
472 473 474 475 476
            if (!def)
                goto error;
        } else {
            if ((def = virNetworkDefParseNode(conn, xml, networks[i])) == NULL)
                goto error;
477
        }
478 479 480 481
        if (!(net = virNetworkAssignDef(conn, &privconn->networks,
                                        def))) {
            virNetworkDefFree(def);
            goto error;
482
        }
483 484 485

        net->persistent = 1;
    }
486
    if (networks != NULL)
487
        VIR_FREE(networks);
488

C
Cole Robinson 已提交
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
    /* Parse Storage Pool list */
    ret = virXPathNodeSet(conn, "/node/pool", ctxt, &pools);
    if (ret < 0) {
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node pool list"));
        goto error;
    }
    for (i = 0 ; i < ret ; i++) {
        virStoragePoolDefPtr def;
        virStoragePoolObjPtr pool;
        char *relFile = virXMLPropString(pools[i], "file");
        if (relFile != NULL) {
            char *absFile = testBuildFilename(file, relFile);
            VIR_FREE(relFile);
            if (!absFile) {
                testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s",
                          _("resolving pool filename"));
                goto error;
            }

            def = virStoragePoolDefParse(conn, NULL, absFile);
            VIR_FREE(absFile);
            if (!def)
                goto error;
        } else {
            xmlBufferPtr buf;
            xmlSaveCtxtPtr sctxt;

            buf = xmlBufferCreate();
            sctxt = xmlSaveToBuffer(buf, NULL, 0);
            xmlSaveTree(sctxt, pools[i]);
            xmlSaveClose(sctxt);
            if ((def = virStoragePoolDefParse(conn,
                                              (const char *) buf->content,
                                              NULL)) == NULL) {
                xmlBufferFree(buf);
                goto error;
            }
        }

        if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools,
                                                def))) {
            virStoragePoolDefFree(def);
            goto error;
        }

        if (testStoragePoolObjSetDefaults(pool) == -1)
            goto error;
        pool->active = 1;
    }
    if (pools != NULL)
        VIR_FREE(pools);

J
Jim Meyering 已提交
541
    xmlXPathFreeContext(ctxt);
542
    xmlFreeDoc(xml);
543

544
    return (0);
545 546

 error:
J
Jim Meyering 已提交
547
    xmlXPathFreeContext(ctxt);
548
    xmlFreeDoc(xml);
549 550
    VIR_FREE(domains);
    VIR_FREE(networks);
C
Cole Robinson 已提交
551
    VIR_FREE(pools);
552 553
    if (fd != -1)
        close(fd);
554
    virDomainObjListFree(&privconn->domains);
555
    virNetworkObjListFree(&privconn->networks);
C
Cole Robinson 已提交
556
    virStoragePoolObjListFree(&privconn->pools);
557
    VIR_FREE(privconn);
558
    conn->privateData = NULL;
559
    return VIR_DRV_OPEN_ERROR;
560 561
}

562

563
static int testOpen(virConnectPtr conn,
564
                    virConnectAuthPtr auth ATTRIBUTE_UNUSED,
565
                    int flags ATTRIBUTE_UNUSED)
566
{
567
    int ret;
568

569
    if (!conn->uri)
570
        return VIR_DRV_OPEN_DECLINED;
571

572
    if (!conn->uri->scheme || STRNEQ(conn->uri->scheme, "test"))
573
        return VIR_DRV_OPEN_DECLINED;
574

575
    /* Remote driver should handle these. */
576
    if (conn->uri->server)
577 578
        return VIR_DRV_OPEN_DECLINED;

579
    if (conn->uri->server)
580 581
        return VIR_DRV_OPEN_DECLINED;

582
    /* From this point on, the connection is for us. */
583 584 585
    if (!conn->uri->path
        || conn->uri->path[0] == '\0'
        || (conn->uri->path[0] == '/' && conn->uri->path[1] == '\0')) {
586
        testError (NULL, VIR_ERR_INVALID_ARG,
J
Jim Meyering 已提交
587
                   "%s", _("testOpen: supply a path or use test:///default"));
588 589
        return VIR_DRV_OPEN_ERROR;
    }
590

591
    if (STREQ(conn->uri->path, "/default"))
592 593
        ret = testOpenDefault(conn);
    else
594
        ret = testOpenFromFile(conn,
595
                               conn->uri->path);
596 597

    return (ret);
598 599
}

600
static int testClose(virConnectPtr conn)
601
{
602
    testConnPtr privconn = conn->privateData;
603

604
    virCapabilitiesFree(privconn->caps);
605
    virDomainObjListFree(&privconn->domains);
606
    virNetworkObjListFree(&privconn->networks);
C
Cole Robinson 已提交
607
    virStoragePoolObjListFree(&privconn->pools);
608

609
    VIR_FREE (privconn);
610
    conn->privateData = NULL;
611
    return 0;
612 613
}

614 615
static int testGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
                          unsigned long *hvVer)
616
{
617 618
    *hvVer = 2;
    return (0);
619 620
}

621
static char *testGetHostname (virConnectPtr conn)
622 623 624 625 626 627
{
    int r;
    char hostname [HOST_NAME_MAX+1], *str;

    r = gethostname (hostname, HOST_NAME_MAX+1);
    if (r == -1) {
628
        testError (conn, VIR_ERR_SYSTEM_ERROR, "%s",
629
                   strerror (errno));
630 631 632 633
        return NULL;
    }
    str = strdup (hostname);
    if (str == NULL) {
634
        testError (conn, VIR_ERR_SYSTEM_ERROR, "%s",
635
                   strerror (errno));
636 637 638 639 640
        return NULL;
    }
    return str;
}

641 642 643 644 645 646 647 648
static int testGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED,
                           const char *type ATTRIBUTE_UNUSED)
{
    return 32;
}

static int testNodeGetInfo(virConnectPtr conn,
                           virNodeInfoPtr info)
649
{
650 651
    testConnPtr privconn = conn->privateData;

652
    memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo));
653
    return (0);
654 655
}

656
static char *testGetCapabilities (virConnectPtr conn)
657
{
658
    testConnPtr privconn = conn->privateData;
659 660
    char *xml;

661
    if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL)
662
        testError(conn, VIR_ERR_NO_MEMORY, NULL);
663 664

    return xml;
665 666
}

667
static int testNumOfDomains(virConnectPtr conn)
668
{
669
    testConnPtr privconn = conn->privateData;
670
    unsigned int numActive = 0, i;
671

672 673
    for (i = 0 ; i < privconn->domains.count ; i++)
        if (virDomainIsActive(privconn->domains.objs[i]))
674
            numActive++;
675

676
    return numActive;
677 678
}

679
static virDomainPtr
680
testDomainCreateXML(virConnectPtr conn, const char *xml,
681
                      unsigned int flags ATTRIBUTE_UNUSED)
682
{
683
    testConnPtr privconn = conn->privateData;
684
    virDomainPtr ret = NULL;
685 686
    virDomainDefPtr def;
    virDomainObjPtr dom;
687

688
    if ((def = virDomainDefParseString(conn, privconn->caps, xml)) == NULL)
689
        goto cleanup;
690

691 692 693
    if ((dom = virDomainAssignDef(conn, &privconn->domains,
                                  def)) == NULL) {
        virDomainDefFree(def);
694
        goto cleanup;
695
    }
696 697
    dom->state = VIR_DOMAIN_RUNNING;
    dom->def->id = privconn->nextDomID++;
698

699
    ret = virGetDomain(conn, def->name, def->uuid);
700 701 702 703
    if (ret)
        ret->id = def->id;

cleanup:
704
    return ret;
705 706 707
}


708 709
static virDomainPtr testLookupDomainByID(virConnectPtr conn,
                                         int id)
710
{
711
    testConnPtr privconn = conn->privateData;
712 713
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
714

715
    if ((dom = virDomainFindByID(&privconn->domains, id)) == NULL) {
716
        testError (conn, VIR_ERR_NO_DOMAIN, NULL);
717
        goto cleanup;
718 719
    }

720
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
721 722 723 724
    if (ret)
        ret->id = dom->def->id;

cleanup:
725
    return ret;
726 727
}

728 729
static virDomainPtr testLookupDomainByUUID(virConnectPtr conn,
                                           const unsigned char *uuid)
730
{
731
    testConnPtr privconn = conn->privateData;
732 733
    virDomainPtr ret = NULL;
    virDomainObjPtr dom ;
734

735
    if ((dom = virDomainFindByUUID(&privconn->domains, uuid)) == NULL) {
736
        testError (conn, VIR_ERR_NO_DOMAIN, NULL);
737
        goto cleanup;
738
    }
739

740
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
741 742 743 744
    if (ret)
        ret->id = dom->def->id;

cleanup:
745
    return ret;
746 747
}

748 749
static virDomainPtr testLookupDomainByName(virConnectPtr conn,
                                           const char *name)
750
{
751
    testConnPtr privconn = conn->privateData;
752 753
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
754

755
    if ((dom = virDomainFindByName(&privconn->domains, name)) == NULL) {
756
        testError (conn, VIR_ERR_NO_DOMAIN, NULL);
757
        goto cleanup;
758
    }
759

760
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
761 762 763 764
    if (ret)
        ret->id = dom->def->id;

cleanup:
765
    return ret;
766 767
}

768 769 770
static int testListDomains (virConnectPtr conn,
                            int *ids,
                            int maxids)
771
{
772
    testConnPtr privconn = conn->privateData;
773
    unsigned int n = 0, i;
774

775 776 777 778
    for (i = 0 ; i < privconn->domains.count && n < maxids ; i++)
        if (virDomainIsActive(privconn->domains.objs[i]))
            ids[n++] = privconn->domains.objs[i]->def->id;

779
    return n;
780 781
}

782
static int testDestroyDomain (virDomainPtr domain)
783
{
784 785
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
786
    int ret = -1;
787 788 789 790 791 792

    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
793
        goto cleanup;
794
    }
795

796
    privdom->state = VIR_DOMAIN_SHUTOFF;
797 798
    privdom->def->id = -1;
    domain->id = -1;
799 800 801
    if (!privdom->persistent) {
        virDomainRemoveInactive(&privconn->domains,
                                privdom);
802
    }
803 804 805 806

    ret = 0;
cleanup:
    return ret;
807 808
}

809
static int testResumeDomain (virDomainPtr domain)
810
{
811 812
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
813
    int ret = -1;
814 815 816 817 818 819

    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
820
        goto cleanup;
821
    }
822

823
    if (privdom->state != VIR_DOMAIN_PAUSED) {
824 825 826
        testError(domain->conn,
                  VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"),
                  domain->name);
827
        goto cleanup;
828
    }
829

830
    privdom->state = VIR_DOMAIN_RUNNING;
831 832 833 834
    ret = 0;

cleanup:
    return ret;
835 836
}

837
static int testPauseDomain (virDomainPtr domain)
838
{
839 840
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
841
    int ret = -1;
842 843 844 845 846 847

    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
848
        goto cleanup;
849
    }
850

851 852
    if (privdom->state == VIR_DOMAIN_SHUTOFF ||
        privdom->state == VIR_DOMAIN_PAUSED) {
853 854 855
        testError(domain->conn,
                  VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"),
                  domain->name);
856
        goto cleanup;
857
    }
858

859
    privdom->state = VIR_DOMAIN_PAUSED;
860 861 862 863
    ret = 0;

cleanup:
    return ret;
864 865
}

866
static int testShutdownDomain (virDomainPtr domain)
867
{
868 869
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
870
    int ret = -1;
871 872 873 874 875 876

    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
877
        goto cleanup;
878
    }
879

880
    if (privdom->state == VIR_DOMAIN_SHUTOFF) {
881 882
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("domain '%s' not running"), domain->name);
883
        goto cleanup;
884
    }
885

886
    privdom->state = VIR_DOMAIN_SHUTOFF;
887
    domain->id = -1;
888
    privdom->def->id = -1;
889
    ret = 0;
890

891 892
cleanup:
    return ret;
893 894 895
}

/* Similar behaviour as shutdown */
896 897
static int testRebootDomain (virDomainPtr domain,
                             unsigned int action ATTRIBUTE_UNUSED)
898
{
899 900
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
901
    int ret = -1;
902 903 904 905 906 907

    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
908
        goto cleanup;
909
    }
910

911 912 913 914
    privdom->state = VIR_DOMAIN_SHUTDOWN;
    switch (privdom->def->onReboot) {
    case VIR_DOMAIN_LIFECYCLE_DESTROY:
        privdom->state = VIR_DOMAIN_SHUTOFF;
915
        domain->id = -1;
916
        privdom->def->id = -1;
917 918
        break;

919 920
    case VIR_DOMAIN_LIFECYCLE_RESTART:
        privdom->state = VIR_DOMAIN_RUNNING;
921 922
        break;

923 924
    case VIR_DOMAIN_LIFECYCLE_PRESERVE:
        privdom->state = VIR_DOMAIN_SHUTOFF;
925
        domain->id = -1;
926
        privdom->def->id = -1;
927 928
        break;

929 930
    case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME:
        privdom->state = VIR_DOMAIN_RUNNING;
931
        break;
932

933
    default:
934
        privdom->state = VIR_DOMAIN_SHUTOFF;
935
        domain->id = -1;
936
        privdom->def->id = -1;
937 938
        break;
    }
939

940 941 942 943
    ret = 0;

cleanup:
    return ret;
944 945
}

946 947
static int testGetDomainInfo (virDomainPtr domain,
                              virDomainInfoPtr info)
948
{
949
    testConnPtr privconn = domain->conn->privateData;
950
    struct timeval tv;
951
    virDomainObjPtr privdom;
952
    int ret = -1;
953 954 955 956 957 958

    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
959
        goto cleanup;
960
    }
961 962

    if (gettimeofday(&tv, NULL) < 0) {
963
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
964
                  "%s", _("getting time of day"));
965
        goto cleanup;
966 967
    }

968 969 970 971 972
    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));
973 974 975 976
    ret = 0;

cleanup:
    return ret;
977 978
}

979
static char *testDomainDumpXML(virDomainPtr domain, int flags);
980

981 982 983 984 985
#define TEST_SAVE_MAGIC "TestGuestMagic"

static int testDomainSave(virDomainPtr domain,
                          const char *path)
{
986
    testConnPtr privconn = domain->conn->privateData;
987 988 989
    char *xml = NULL;
    int fd = -1;
    int len;
990
    virDomainObjPtr privdom;
991
    int ret = -1;
992 993 994 995 996 997

    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
998
        goto cleanup;
999
    }
1000

1001
    xml = testDomainDumpXML(domain, 0);
1002
    if (xml == NULL) {
1003 1004 1005
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("saving domain '%s' failed to allocate space for metadata: %s"),
                  domain->name, strerror(errno));
1006
        goto cleanup;
1007
    }
1008 1009

    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
1010 1011 1012
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("saving domain '%s' to '%s': open failed: %s"),
                  domain->name, path, strerror(errno));
1013
        goto cleanup;
1014
    }
1015
    len = strlen(xml);
1016
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
1017 1018 1019
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("saving domain '%s' to '%s': write failed: %s"),
                  domain->name, path, strerror(errno));
1020
        goto cleanup;
1021
    }
1022
    if (safewrite(fd, (char*)&len, sizeof(len)) < 0) {
1023 1024 1025
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("saving domain '%s' to '%s': write failed: %s"),
                  domain->name, path, strerror(errno));
1026
        goto cleanup;
1027
    }
1028
    if (safewrite(fd, xml, len) < 0) {
1029 1030 1031
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("saving domain '%s' to '%s': write failed: %s"),
                  domain->name, path, strerror(errno));
1032
        goto cleanup;
1033
    }
1034

1035
    if (close(fd) < 0) {
1036 1037 1038
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("saving domain '%s' to '%s': write failed: %s"),
                  domain->name, path, strerror(errno));
1039
        goto cleanup;
1040
    }
1041 1042
    fd = -1;

1043 1044 1045 1046
    privdom->state = VIR_DOMAIN_SHUTOFF;
    if (!privdom->persistent) {
        virDomainRemoveInactive(&privconn->domains,
                                privdom);
1047
    }
1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062
    ret = 0;

cleanup:
    VIR_FREE(xml);

    /* Don't report failure in close or unlink, because
     * in either case we're already in a failure scenario
     * and have reported a earlier error */
    if (ret != 0) {
        if (fd != -1)
            close(fd);
        unlink(path);
    }

    return ret;
1063 1064
}

1065 1066
static int testDomainRestore(virConnectPtr conn,
                             const char *path)
1067
{
1068
    testConnPtr privconn = conn->privateData;
1069
    char *xml = NULL;
1070
    char magic[15];
1071 1072 1073
    int fd = -1;
    int len;
    virDomainDefPtr def = NULL;
1074
    virDomainObjPtr dom;
1075
    int ret = -1;
1076 1077

    if ((fd = open(path, O_RDONLY)) < 0) {
1078
        testError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1079
                  "%s", _("cannot read domain image"));
1080
        goto cleanup;
1081
    }
1082
    if (read(fd, magic, sizeof(magic)) != sizeof(magic)) {
1083
        testError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1084
                  "%s", _("incomplete save header"));
1085
        goto cleanup;
1086
    }
1087
    if (memcmp(magic, TEST_SAVE_MAGIC, sizeof(magic))) {
1088
        testError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1089
                  "%s", _("mismatched header magic"));
1090
        goto cleanup;
1091 1092
    }
    if (read(fd, (char*)&len, sizeof(len)) != sizeof(len)) {
1093
        testError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1094
                  "%s", _("failed to read metadata length"));
1095
        goto cleanup;
1096 1097
    }
    if (len < 1 || len > 8192) {
1098
        testError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1099
                  "%s", _("length of metadata out of range"));
1100
        goto cleanup;
1101
    }
1102
    if (VIR_ALLOC_N(xml, len+1) < 0) {
1103
        testError(conn, VIR_ERR_NO_MEMORY, "xml");
1104
        goto cleanup;
1105 1106
    }
    if (read(fd, xml, len) != len) {
1107
        testError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1108
                  "%s", _("incomplete metdata"));
1109
        goto cleanup;
1110 1111
    }
    xml[len] = '\0';
1112 1113 1114

    def = virDomainDefParseString(conn, privconn->caps, xml);
    if (!def)
1115
        goto cleanup;
1116 1117

    if ((dom = virDomainAssignDef(conn, &privconn->domains,
1118 1119 1120
                                  def)) == NULL)
        goto cleanup;

1121 1122
    dom->state = VIR_DOMAIN_RUNNING;
    dom->def->id = privconn->nextDomID++;
1123 1124 1125 1126 1127 1128 1129 1130 1131
    def = NULL;
    ret = dom->def->id;

cleanup:
    virDomainDefFree(def);
    VIR_FREE(xml);
    if (fd != -1)
        close(fd);
    return ret;
1132 1133
}

1134 1135 1136
static int testDomainCoreDump(virDomainPtr domain,
                              const char *to,
                              int flags ATTRIBUTE_UNUSED)
1137
{
1138
    testConnPtr privconn = domain->conn->privateData;
1139
    int fd = -1;
1140
    virDomainObjPtr privdom;
1141
    int ret = -1;
1142 1143 1144 1145 1146 1147

    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1148
        goto cleanup;
1149
    }
1150 1151

    if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
1152 1153 1154
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("domain '%s' coredump: failed to open %s: %s"),
                  domain->name, to, strerror (errno));
1155
        goto cleanup;
1156
    }
1157
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
1158 1159 1160
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("domain '%s' coredump: failed to write header to %s: %s"),
                  domain->name, to, strerror (errno));
1161
        goto cleanup;
1162
    }
1163
    if (close(fd) < 0) {
1164 1165 1166
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("domain '%s' coredump: write failed: %s: %s"),
                  domain->name, to, strerror (errno));
1167
        goto cleanup;
1168
    }
1169 1170 1171 1172
    privdom->state = VIR_DOMAIN_SHUTOFF;
    if (!privdom->persistent) {
        virDomainRemoveInactive(&privconn->domains,
                                privdom);
1173
    }
1174 1175 1176 1177 1178 1179
    ret = 0;

cleanup:
    if (fd != -1)
        close(fd);
    return ret;
1180 1181
}

1182 1183 1184
static char *testGetOSType(virDomainPtr dom) {
    char *ret = strdup("linux");
    if (!ret)
1185
        testError(dom->conn, VIR_ERR_NO_MEMORY, NULL);
1186
    return ret;
1187 1188 1189
}

static unsigned long testGetMaxMemory(virDomainPtr domain) {
1190 1191
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1192
    unsigned long ret = -1;
1193 1194 1195 1196 1197 1198

    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1199
        goto cleanup;
1200
    }
1201

1202 1203 1204 1205
    ret = privdom->def->maxmem;

cleanup:
    return ret;
1206 1207 1208 1209 1210
}

static int testSetMaxMemory(virDomainPtr domain,
                            unsigned long memory)
{
1211 1212
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1213
    int ret = -1;
1214 1215 1216 1217 1218 1219

    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1220
        goto cleanup;
1221
    }
1222 1223

    /* XXX validate not over host memory wrt to other domains */
1224
    privdom->def->maxmem = memory;
1225 1226 1227 1228
    ret = 0;

cleanup:
    return ret;
1229 1230
}

1231 1232 1233
static int testSetMemory(virDomainPtr domain,
                         unsigned long memory)
{
1234 1235
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1236
    int ret = -1;
1237 1238 1239 1240 1241 1242

    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1243
        goto cleanup;
1244
    }
1245

1246
    if (memory > privdom->def->maxmem) {
1247
        testError(domain->conn,
1248
                  VIR_ERR_INVALID_ARG, __FUNCTION__);
1249
        goto cleanup;
1250
    }
1251

1252
    privdom->def->memory = memory;
1253 1254 1255 1256
    ret = 0;

cleanup:
    return ret;
1257 1258 1259 1260
}

static int testSetVcpus(virDomainPtr domain,
                        unsigned int nrCpus) {
1261 1262
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1263 1264
    int ret = -1;

1265 1266 1267
    if ((privdom = virDomainFindByName(&privconn->domains,
                                       domain->name)) == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1268
        goto cleanup;
1269
    }
1270

1271 1272
    /* We allow more cpus in guest than host */
    if (nrCpus > 32) {
1273
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1274
        goto cleanup;
1275
    }
1276

1277
    privdom->def->vcpus = nrCpus;
1278 1279 1280 1281
    ret = 0;

cleanup:
    return ret;
1282 1283
}

1284
static char *testDomainDumpXML(virDomainPtr domain, int flags)
1285
{
1286
    testConnPtr privconn = domain->conn->privateData;
1287
    virDomainDefPtr def;
1288
    virDomainObjPtr privdom;
1289 1290
    char *ret = NULL;

1291 1292 1293
    if ((privdom = virDomainFindByName(&privconn->domains,
                                       domain->name)) == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1294
        goto cleanup;
1295
    }
1296

1297 1298
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
1299

1300 1301 1302 1303 1304 1305
    ret = virDomainDefFormat(domain->conn,
                             def,
                             flags);

cleanup:
    return ret;
1306
}
1307

1308
static int testNumOfDefinedDomains(virConnectPtr conn) {
1309
    testConnPtr privconn = conn->privateData;
1310
    unsigned int numInactive = 0, i;
1311

1312 1313
    for (i = 0 ; i < privconn->domains.count ; i++)
        if (!virDomainIsActive(privconn->domains.objs[i]))
1314
            numInactive++;
1315

1316
    return numInactive;
1317 1318
}

1319 1320 1321
static int testListDefinedDomains(virConnectPtr conn,
                                  char **const names,
                                  int maxnames) {
1322
    testConnPtr privconn = conn->privateData;
1323
    unsigned int n = 0, i;
1324 1325

    memset(names, 0, sizeof(*names)*maxnames);
1326 1327 1328
    for (i = 0 ; i < privconn->domains.count && n < maxnames ; i++)
        if (!virDomainIsActive(privconn->domains.objs[i]) &&
            !(names[n++] = strdup(privconn->domains.objs[i]->def->name)))
1329
            goto no_memory;
1330

1331 1332 1333
    return n;

no_memory:
1334
    testError(conn, VIR_ERR_NO_MEMORY, NULL);
1335 1336 1337
    for (n = 0 ; n < maxnames ; n++)
        VIR_FREE(names[n]);
    return -1;
1338 1339
}

1340
static virDomainPtr testDomainDefineXML(virConnectPtr conn,
1341
                                        const char *xml) {
1342
    testConnPtr privconn = conn->privateData;
1343
    virDomainPtr ret = NULL;
1344 1345
    virDomainDefPtr def;
    virDomainObjPtr dom;
1346

1347
    if ((def = virDomainDefParseString(conn, privconn->caps, xml)) == NULL)
1348
        goto cleanup;
1349

1350 1351
    if ((dom = virDomainAssignDef(conn, &privconn->domains,
                                  def)) == NULL) {
1352
        goto cleanup;
1353 1354 1355
    }
    dom->persistent = 1;
    dom->def->id = -1;
1356

1357
    ret = virGetDomain(conn, def->name, def->uuid);
1358 1359 1360 1361 1362 1363
    def = NULL;
    if (ret)
        ret->id = -1;

cleanup:
    virDomainDefFree(def);
1364
    return ret;
1365 1366
}

1367 1368 1369
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
                                      int startCell, int maxCells) {
1370
    testConnPtr privconn = conn->privateData;
1371
    int i, j;
1372
    int ret = -1;
1373 1374

    if (startCell > privconn->numCells) {
1375
        testError(conn, VIR_ERR_INVALID_ARG,
J
Jim Meyering 已提交
1376
                  "%s", _("Range exceeds available cells"));
1377
        goto cleanup;
1378 1379 1380 1381 1382 1383 1384
    }

    for (i = startCell, j = 0;
         (i < privconn->numCells && j < maxCells) ;
         ++i, ++j) {
        freemems[j] = privconn->cells[i].mem;
    }
1385
    ret = j;
1386

1387 1388
cleanup:
    return ret;
1389 1390 1391
}


1392
static int testDomainCreate(virDomainPtr domain) {
1393 1394
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1395
    int ret = -1;
1396 1397 1398 1399 1400 1401

    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1402
        goto cleanup;
1403
    }
1404

1405
    if (privdom->state != VIR_DOMAIN_SHUTOFF) {
1406 1407
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Domain '%s' is already running"), domain->name);
1408
        goto cleanup;
1409 1410
    }

1411 1412
    domain->id = privdom->def->id = privconn->nextDomID++;
    privdom->state = VIR_DOMAIN_RUNNING;
1413
    ret = 0;
1414

1415 1416
cleanup:
    return ret;
1417 1418 1419
}

static int testDomainUndefine(virDomainPtr domain) {
1420 1421
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1422
    int ret = -1;
1423 1424 1425 1426 1427 1428

    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1429
        goto cleanup;
1430
    }
1431

1432
    if (privdom->state != VIR_DOMAIN_SHUTOFF) {
1433 1434
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Domain '%s' is still running"), domain->name);
1435
        goto cleanup;
1436 1437
    }

1438 1439 1440
    privdom->state = VIR_DOMAIN_SHUTOFF;
    virDomainRemoveInactive(&privconn->domains,
                            privdom);
1441
    ret = 0;
1442

1443 1444
cleanup:
    return ret;
1445 1446
}

1447 1448 1449
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
1450 1451
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1452
    int ret = -1;
1453 1454 1455 1456 1457 1458

    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1459
        goto cleanup;
1460 1461
    }

1462
    *autostart = privdom->autostart;
1463 1464 1465 1466
    ret = 0;

cleanup:
    return ret;
1467 1468 1469 1470 1471 1472
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
1473 1474
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1475
    int ret = -1;
1476 1477 1478 1479 1480 1481

    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1482
        goto cleanup;
1483 1484
    }

1485
    privdom->autostart = autostart ? 1 : 0;
1486 1487 1488 1489
    ret = 0;

cleanup:
    return ret;
1490
}
1491

1492 1493 1494
static char *testDomainGetSchedulerType(virDomainPtr domain,
                                        int *nparams)
{
1495 1496
    char *type = NULL;

1497 1498
    *nparams = 1;
    type = strdup("fair");
1499
    if (!type)
1500
        testError(domain->conn, VIR_ERR_NO_MEMORY, "schedular");
1501

1502 1503 1504 1505 1506 1507 1508
    return type;
}

static int testDomainGetSchedulerParams(virDomainPtr domain,
                                        virSchedParameterPtr params,
                                        int *nparams)
{
1509 1510
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1511
    int ret = -1;
1512 1513 1514 1515 1516 1517

    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1518
        goto cleanup;
1519 1520
    }

1521
    if (*nparams != 1) {
1522
        testError(domain->conn, VIR_ERR_INVALID_ARG, "nparams");
1523
        goto cleanup;
1524
    }
1525 1526
    strcpy(params[0].field, "weight");
    params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT;
1527 1528 1529
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
    params[0].value.ui = 50;
1530 1531 1532 1533
    ret = 0;

cleanup:
    return ret;
1534
}
1535 1536


1537 1538 1539 1540
static int testDomainSetSchedulerParams(virDomainPtr domain,
                                        virSchedParameterPtr params,
                                        int nparams)
{
1541 1542
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1543
    int ret = -1;
1544 1545 1546 1547 1548 1549

    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1550
        goto cleanup;
1551 1552
    }

1553
    if (nparams != 1) {
1554
        testError(domain->conn, VIR_ERR_INVALID_ARG, "nparams");
1555
        goto cleanup;
1556
    }
1557
    if (STRNEQ(params[0].field, "weight")) {
1558
        testError(domain->conn, VIR_ERR_INVALID_ARG, "field");
1559
        goto cleanup;
1560 1561
    }
    if (params[0].type != VIR_DOMAIN_SCHED_FIELD_UINT) {
1562
        testError(domain->conn, VIR_ERR_INVALID_ARG, "type");
1563
        goto cleanup;
1564
    }
1565 1566
    /* XXX */
    /*privdom->weight = params[0].value.ui;*/
1567 1568 1569 1570
    ret = 0;

cleanup:
    return ret;
1571 1572 1573
}

static virDrvOpenStatus testOpenNetwork(virConnectPtr conn,
1574
                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591
                                        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)
{
1592 1593
    testConnPtr privconn = conn->privateData;
    virNetworkObjPtr net;
1594
    virNetworkPtr ret = NULL;
1595

1596
    if ((net = virNetworkFindByUUID(&privconn->networks, uuid)) == NULL) {
1597
        testError (conn, VIR_ERR_NO_NETWORK, NULL);
1598
        goto cleanup;
1599 1600
    }

1601 1602 1603 1604
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

cleanup:
    return ret;
1605
}
1606

1607
static virNetworkPtr testLookupNetworkByName(virConnectPtr conn,
1608
                                             const char *name)
1609
{
1610
    testConnPtr privconn = conn->privateData;
1611 1612
    virNetworkObjPtr net;
    virNetworkPtr ret = NULL;
1613

1614
    if ((net = virNetworkFindByName(&privconn->networks, name)) == NULL) {
1615
        testError (conn, VIR_ERR_NO_NETWORK, NULL);
1616
        goto cleanup;
1617 1618
    }

1619 1620 1621 1622
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

cleanup:
    return ret;
1623 1624 1625 1626
}


static int testNumNetworks(virConnectPtr conn) {
1627
    testConnPtr privconn = conn->privateData;
1628
    int numActive = 0, i;
1629

1630 1631
    for (i = 0 ; i < privconn->networks.count ; i++)
        if (virNetworkIsActive(privconn->networks.objs[i]))
1632
            numActive++;
1633

1634
    return numActive;
1635 1636 1637
}

static int testListNetworks(virConnectPtr conn, char **const names, int nnames) {
1638
    testConnPtr privconn = conn->privateData;
1639
    int n = 0, i;
1640

1641
    memset(names, 0, sizeof(*names)*nnames);
1642 1643 1644
    for (i = 0 ; i < privconn->networks.count && n < nnames ; i++)
        if (virNetworkIsActive(privconn->networks.objs[i]) &&
            !(names[n++] = strdup(privconn->networks.objs[i]->def->name)))
1645
            goto no_memory;
1646

1647 1648 1649
    return n;

no_memory:
1650
    testError(conn, VIR_ERR_NO_MEMORY, NULL);
1651 1652
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
1653
    return -1;
1654 1655 1656
}

static int testNumDefinedNetworks(virConnectPtr conn) {
1657
    testConnPtr privconn = conn->privateData;
1658
    int numInactive = 0, i;
1659

1660 1661
    for (i = 0 ; i < privconn->networks.count ; i++)
        if (!virNetworkIsActive(privconn->networks.objs[i]))
1662
            numInactive++;
1663

1664
    return numInactive;
1665 1666 1667
}

static int testListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
1668
    testConnPtr privconn = conn->privateData;
1669
    int n = 0, i;
1670

1671
    memset(names, 0, sizeof(*names)*nnames);
1672 1673 1674
    for (i = 0 ; i < privconn->networks.count && n < nnames ; i++)
        if (!virNetworkIsActive(privconn->networks.objs[i]) &&
            !(names[n++] = strdup(privconn->networks.objs[i]->def->name)))
1675
            goto no_memory;
1676

1677 1678 1679
    return n;

no_memory:
1680
    testError(conn, VIR_ERR_NO_MEMORY, NULL);
1681 1682
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
1683
    return -1;
1684 1685 1686
}

static virNetworkPtr testNetworkCreate(virConnectPtr conn, const char *xml) {
1687
    testConnPtr privconn = conn->privateData;
1688 1689
    virNetworkDefPtr def;
    virNetworkObjPtr net;
1690
    virNetworkPtr ret = NULL;
1691

1692
    if ((def = virNetworkDefParseString(conn, xml)) == NULL)
1693
        goto cleanup;
1694

1695 1696
    if ((net = virNetworkAssignDef(conn, &privconn->networks,
                                   def)) == NULL) {
1697
        goto cleanup;
1698
    }
1699
    net->active = 1;
1700 1701 1702
    def = NULL;

    ret = virGetNetwork(conn, def->name, def->uuid);
1703

1704 1705 1706
cleanup:
    virNetworkDefFree(def);
    return ret;
1707 1708 1709
}

static virNetworkPtr testNetworkDefine(virConnectPtr conn, const char *xml) {
1710
    testConnPtr privconn = conn->privateData;
1711 1712
    virNetworkDefPtr def;
    virNetworkObjPtr net;
1713
    virNetworkPtr ret = NULL;
1714

1715
    if ((def = virNetworkDefParseString(conn, xml)) == NULL)
1716
        goto cleanup;
1717

1718 1719
    if ((net = virNetworkAssignDef(conn, &privconn->networks,
                                   def)) == NULL) {
1720
        goto cleanup;
1721
    }
1722
    net->persistent = 1;
1723
    def = NULL;
1724

1725 1726 1727 1728 1729
    ret = virGetNetwork(conn, def->name, def->uuid);

cleanup:
    virNetworkDefFree(def);
    return ret;
1730 1731 1732
}

static int testNetworkUndefine(virNetworkPtr network) {
1733 1734
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
1735
    int ret = -1;
1736 1737 1738 1739 1740 1741

    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1742
        goto cleanup;
1743
    }
1744

1745
    if (virNetworkIsActive(privnet)) {
1746 1747
        testError(network->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Network '%s' is still running"), network->name);
1748
        goto cleanup;
1749 1750
    }

1751 1752
    virNetworkRemoveInactive(&privconn->networks,
                             privnet);
1753
    ret = 0;
1754

1755 1756
cleanup:
    return ret;
1757 1758 1759
}

static int testNetworkStart(virNetworkPtr network) {
1760 1761
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
1762
    int ret = -1;
1763 1764 1765 1766 1767 1768

    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1769
        goto cleanup;
1770
    }
1771

1772
    if (virNetworkIsActive(privnet)) {
1773 1774
        testError(network->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Network '%s' is already running"), network->name);
1775
        goto cleanup;
1776 1777
    }

1778
    privnet->active = 1;
1779
    ret = 0;
1780

1781 1782
cleanup:
    return ret;
1783 1784 1785
}

static int testNetworkDestroy(virNetworkPtr network) {
1786 1787
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
1788
    int ret = -1;
1789 1790 1791 1792 1793 1794

    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1795
        goto cleanup;
1796
    }
1797

1798 1799 1800 1801
    privnet->active = 0;
    if (!privnet->persistent) {
        virNetworkRemoveInactive(&privconn->networks,
                                 privnet);
1802
    }
1803 1804 1805 1806
    ret = 0;

cleanup:
    return ret;
1807 1808 1809
}

static char *testNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) {
1810 1811
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
1812
    char *ret = NULL;
1813 1814 1815 1816 1817 1818

    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1819
        goto cleanup;
1820
    }
1821

1822 1823 1824 1825
    ret = virNetworkDefFormat(network->conn, privnet->def);

cleanup:
    return ret;
1826 1827 1828
}

static char *testNetworkGetBridgeName(virNetworkPtr network) {
1829
    testConnPtr privconn = network->conn->privateData;
1830
    char *bridge = NULL;
1831 1832 1833 1834 1835 1836 1837
    virNetworkObjPtr privnet;

    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1838
        goto cleanup;
1839 1840
    }

1841 1842
    if (privnet->def->bridge &&
        !(bridge = strdup(privnet->def->bridge))) {
1843
        testError(network->conn, VIR_ERR_NO_MEMORY, "network");
1844
        goto cleanup;
1845
    }
1846 1847

cleanup:
1848 1849 1850 1851 1852
    return bridge;
}

static int testNetworkGetAutostart(virNetworkPtr network,
                                   int *autostart) {
1853 1854
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
1855
    int ret = -1;
1856 1857 1858 1859 1860 1861

    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1862
        goto cleanup;
1863 1864
    }

1865
    *autostart = privnet->autostart;
1866 1867 1868 1869
    ret = 0;

cleanup:
    return ret;
1870 1871 1872 1873
}

static int testNetworkSetAutostart(virNetworkPtr network,
                                   int autostart) {
1874 1875
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
1876
    int ret = -1;
1877 1878 1879 1880 1881 1882

    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1883
        goto cleanup;
1884 1885
    }

1886
    privnet->autostart = autostart ? 1 : 0;
1887 1888 1889 1890
    ret = 0;

cleanup:
    return ret;
1891
}
1892

C
Cole Robinson 已提交
1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912

/*
 * Storage Driver routines
 */

static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool) {

    pool->def->capacity = defaultPoolCap;
    pool->def->allocation = defaultPoolAlloc;
    pool->def->available = defaultPoolCap - defaultPoolAlloc;

    pool->configFile = strdup("\0");
    if (!pool->configFile) {
        testError(NULL, VIR_ERR_NO_MEMORY, "configFile");
        return -1;
    }

    return 0;
}

1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927
static virDrvOpenStatus testStorageOpen(virConnectPtr conn,
                                        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;
}

C
Cole Robinson 已提交
1928 1929 1930
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
                            const unsigned char *uuid) {
1931
    testConnPtr privconn = conn->privateData;
1932 1933
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
1934

1935 1936 1937
    pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid);

    if (pool == NULL) {
C
Cole Robinson 已提交
1938
        testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL);
1939
        goto cleanup;
C
Cole Robinson 已提交
1940 1941
    }

1942 1943 1944 1945
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
    return ret;
C
Cole Robinson 已提交
1946 1947 1948 1949 1950
}

static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
                            const char *name) {
1951
    testConnPtr privconn = conn->privateData;
1952 1953
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
1954

1955 1956 1957
    pool = virStoragePoolObjFindByName(&privconn->pools, name);

    if (pool == NULL) {
C
Cole Robinson 已提交
1958
        testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL);
1959
        goto cleanup;
C
Cole Robinson 已提交
1960 1961
    }

1962 1963 1964 1965
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
    return ret;
C
Cole Robinson 已提交
1966 1967 1968 1969 1970 1971 1972 1973 1974
}

static virStoragePoolPtr
testStoragePoolLookupByVolume(virStorageVolPtr vol) {
    return testStoragePoolLookupByName(vol->conn, vol->pool);
}

static int
testStorageNumPools(virConnectPtr conn) {
1975
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988
    int numActive = 0, i;

    for (i = 0 ; i < privconn->pools.count ; i++)
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numActive++;

    return numActive;
}

static int
testStorageListPools(virConnectPtr conn,
                     char **const names,
                     int nnames) {
1989
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003
    int n = 0, i;

    memset(names, 0, sizeof(*names)*nnames);
    for (i = 0 ; i < privconn->pools.count && n < nnames ; i++)
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
            !(names[n++] = strdup(privconn->pools.objs[i]->def->name)))
            goto no_memory;

    return n;

no_memory:
    testError(conn, VIR_ERR_NO_MEMORY, NULL);
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
2004
    return -1;
C
Cole Robinson 已提交
2005 2006 2007 2008
}

static int
testStorageNumDefinedPools(virConnectPtr conn) {
2009
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022
    int numInactive = 0, i;

    for (i = 0 ; i < privconn->pools.count ; i++)
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numInactive++;

    return numInactive;
}

static int
testStorageListDefinedPools(virConnectPtr conn,
                            char **const names,
                            int nnames) {
2023
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037
    int n = 0, i;

    memset(names, 0, sizeof(*names)*nnames);
    for (i = 0 ; i < privconn->pools.count && n < nnames ; i++)
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
            !(names[n++] = strdup(privconn->pools.objs[i]->def->name)))
            goto no_memory;

    return n;

no_memory:
    testError(conn, VIR_ERR_NO_MEMORY, NULL);
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
2038
    return -1;
C
Cole Robinson 已提交
2039 2040 2041 2042 2043 2044 2045
}

static int
testStoragePoolRefresh(virStoragePoolPtr obj,
                       unsigned int flags ATTRIBUTE_UNUSED);

static int
2046
testStoragePoolStart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2047
                     unsigned int flags ATTRIBUTE_UNUSED) {
2048 2049
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2050
    int ret = -1;
2051 2052 2053 2054 2055 2056

    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2057
        goto cleanup;
2058 2059
    }

2060 2061 2062 2063 2064
    if (virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is already active"), pool->name);
        goto cleanup;
    }
C
Cole Robinson 已提交
2065

2066
    if (testStoragePoolRefresh(pool, 0) == 0)
2067
        goto cleanup;
C
Cole Robinson 已提交
2068
    privpool->active = 1;
2069
    ret = 0;
C
Cole Robinson 已提交
2070

2071 2072
cleanup:
    return ret;
C
Cole Robinson 已提交
2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088
}

static char *
testStorageFindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                           const char *type ATTRIBUTE_UNUSED,
                           const char *srcSpec ATTRIBUTE_UNUSED,
                           unsigned int flags ATTRIBUTE_UNUSED)
{
    return NULL;
}


static virStoragePoolPtr
testStoragePoolCreate(virConnectPtr conn,
                      const char *xml,
                      unsigned int flags ATTRIBUTE_UNUSED) {
2089
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
2090 2091
    virStoragePoolDefPtr def;
    virStoragePoolObjPtr pool;
2092
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
2093 2094

    if (!(def = virStoragePoolDefParse(conn, xml, NULL)))
2095
        goto cleanup;
C
Cole Robinson 已提交
2096

2097 2098 2099 2100
    pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid);
    if (!pool)
        pool = virStoragePoolObjFindByName(&privconn->pools, def->name);
    if (pool) {
C
Cole Robinson 已提交
2101 2102
        testError(conn, VIR_ERR_INTERNAL_ERROR,
                  "%s", _("storage pool already exists"));
2103
        goto cleanup;
C
Cole Robinson 已提交
2104 2105 2106 2107 2108
    }

    if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, def))) {
        return NULL;
    }
2109
    def = NULL;
C
Cole Robinson 已提交
2110 2111 2112

    if (testStoragePoolObjSetDefaults(pool) == -1) {
        virStoragePoolObjRemove(&privconn->pools, pool);
2113 2114
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
2115 2116 2117
    }
    pool->active = 1;

2118 2119 2120 2121 2122
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
    virStoragePoolDefFree(def);
    return ret;
C
Cole Robinson 已提交
2123 2124 2125 2126 2127 2128
}

static virStoragePoolPtr
testStoragePoolDefine(virConnectPtr conn,
                      const char *xml,
                      unsigned int flags ATTRIBUTE_UNUSED) {
2129
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
2130 2131
    virStoragePoolDefPtr def;
    virStoragePoolObjPtr pool;
2132
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
2133 2134

    if (!(def = virStoragePoolDefParse(conn, xml, NULL)))
2135
        goto cleanup;
C
Cole Robinson 已提交
2136 2137 2138 2139 2140 2141

    def->capacity = defaultPoolCap;
    def->allocation = defaultPoolAlloc;
    def->available = defaultPoolCap - defaultPoolAlloc;

    if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, def))) {
2142
        goto cleanup;
C
Cole Robinson 已提交
2143
    }
2144
    def = NULL;
C
Cole Robinson 已提交
2145 2146 2147

    if (testStoragePoolObjSetDefaults(pool) == -1) {
        virStoragePoolObjRemove(&privconn->pools, pool);
2148 2149
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
2150 2151
    }

2152 2153 2154 2155 2156
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
    virStoragePoolDefFree(def);
    return ret;
C
Cole Robinson 已提交
2157 2158 2159
}

static int
2160 2161 2162
testStoragePoolUndefine(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2163
    int ret = -1;
2164 2165 2166 2167 2168 2169

    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2170
        goto cleanup;
2171 2172
    }

2173 2174 2175 2176 2177
    if (virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is already active"), pool->name);
        goto cleanup;
    }
C
Cole Robinson 已提交
2178 2179

    virStoragePoolObjRemove(&privconn->pools, privpool);
2180
    ret = 0;
C
Cole Robinson 已提交
2181

2182 2183
cleanup:
    return ret;
C
Cole Robinson 已提交
2184 2185 2186
}

static int
2187
testStoragePoolBuild(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2188
                     unsigned int flags ATTRIBUTE_UNUSED) {
2189 2190
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2191
    int ret = -1;
2192 2193 2194 2195 2196 2197

    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2198
        goto cleanup;
2199 2200
    }

2201 2202 2203 2204 2205
    if (virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is already active"), pool->name);
        goto cleanup;
    }
C
Cole Robinson 已提交
2206

2207 2208
cleanup:
    return ret;
C
Cole Robinson 已提交
2209 2210 2211 2212
}


static int
2213 2214 2215
testStoragePoolDestroy(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2216
    int ret = -1;
2217 2218 2219 2220 2221 2222

    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2223
        goto cleanup;
2224 2225 2226 2227 2228
    }

    if (!virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is not active"), pool->name);
2229
        goto cleanup;
2230
    }
C
Cole Robinson 已提交
2231 2232 2233 2234 2235

    privpool->active = 0;

    if (privpool->configFile == NULL)
        virStoragePoolObjRemove(&privconn->pools, privpool);
2236
    ret = 0;
C
Cole Robinson 已提交
2237

2238 2239
cleanup:
    return ret;
C
Cole Robinson 已提交
2240 2241 2242 2243
}


static int
2244
testStoragePoolDelete(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2245
                      unsigned int flags ATTRIBUTE_UNUSED) {
2246 2247
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2248
    int ret = -1;
2249 2250 2251 2252 2253 2254

    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2255 2256 2257 2258 2259 2260 2261
        goto cleanup;
    }

    if (virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is already active"), pool->name);
        goto cleanup;
2262 2263
    }

2264
    ret = 0;
C
Cole Robinson 已提交
2265

2266 2267
cleanup:
    return ret;
C
Cole Robinson 已提交
2268 2269 2270 2271
}


static int
2272
testStoragePoolRefresh(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2273
                       unsigned int flags ATTRIBUTE_UNUSED) {
2274 2275
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2276
    int ret = -1;
2277 2278 2279 2280 2281 2282

    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2283
        goto cleanup;
2284 2285 2286 2287 2288
    }

    if (!virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is not active"), pool->name);
2289
        goto cleanup;
2290
    }
2291
    ret = 0;
C
Cole Robinson 已提交
2292

2293 2294
cleanup:
    return ret;
C
Cole Robinson 已提交
2295 2296 2297 2298
}


static int
2299
testStoragePoolGetInfo(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2300
                       virStoragePoolInfoPtr info) {
2301 2302
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2303
    int ret = -1;
2304 2305 2306 2307 2308 2309

    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2310
        goto cleanup;
2311
    }
C
Cole Robinson 已提交
2312 2313 2314 2315 2316 2317 2318 2319 2320

    memset(info, 0, sizeof(virStoragePoolInfo));
    if (privpool->active)
        info->state = VIR_STORAGE_POOL_RUNNING;
    else
        info->state = VIR_STORAGE_POOL_INACTIVE;
    info->capacity = privpool->def->capacity;
    info->allocation = privpool->def->allocation;
    info->available = privpool->def->available;
2321
    ret = 0;
C
Cole Robinson 已提交
2322

2323 2324
cleanup:
    return ret;
C
Cole Robinson 已提交
2325 2326 2327
}

static char *
2328
testStoragePoolDumpXML(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2329
                       unsigned int flags ATTRIBUTE_UNUSED) {
2330 2331
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2332
    char *ret = NULL;
2333 2334 2335

    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
C
Cole Robinson 已提交
2336

2337 2338
    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2339
        goto cleanup;
2340 2341
    }

2342 2343 2344 2345
    ret = virStoragePoolDefFormat(pool->conn, privpool->def);

cleanup:
    return ret;
C
Cole Robinson 已提交
2346 2347 2348
}

static int
2349
testStoragePoolGetAutostart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2350
                            int *autostart) {
2351 2352
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2353
    int ret = -1;
2354 2355 2356 2357 2358 2359

    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2360
        goto cleanup;
2361
    }
C
Cole Robinson 已提交
2362 2363 2364 2365 2366 2367

    if (!privpool->configFile) {
        *autostart = 0;
    } else {
        *autostart = privpool->autostart;
    }
2368
    ret = 0;
C
Cole Robinson 已提交
2369

2370 2371
cleanup:
    return ret;
C
Cole Robinson 已提交
2372 2373 2374
}

static int
2375
testStoragePoolSetAutostart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2376
                            int autostart) {
2377 2378
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2379
    int ret = -1;
2380 2381 2382 2383 2384 2385

    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2386
        goto cleanup;
2387
    }
C
Cole Robinson 已提交
2388 2389

    if (!privpool->configFile) {
2390
        testError(pool->conn, VIR_ERR_INVALID_ARG,
C
Cole Robinson 已提交
2391
                  "%s", _("pool has no config file"));
2392
        goto cleanup;
C
Cole Robinson 已提交
2393 2394 2395 2396
    }

    autostart = (autostart != 0);
    privpool->autostart = autostart;
2397 2398 2399 2400
    ret = 0;

cleanup:
    return ret;
C
Cole Robinson 已提交
2401 2402 2403 2404
}


static int
2405 2406 2407
testStoragePoolNumVolumes(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2408
    int ret = -1;
2409 2410 2411 2412 2413 2414

    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2415
        goto cleanup;
2416 2417 2418 2419 2420
    }

    if (!virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is not active"), pool->name);
2421
        goto cleanup;
2422
    }
C
Cole Robinson 已提交
2423

2424 2425 2426 2427
    ret = privpool->volumes.count;

cleanup:
    return ret;
C
Cole Robinson 已提交
2428 2429 2430
}

static int
2431
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2432 2433
                           char **const names,
                           int maxnames) {
2434 2435
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
C
Cole Robinson 已提交
2436 2437
    int i = 0, n = 0;

2438
    memset(names, 0, maxnames * sizeof(*names));
2439 2440 2441 2442 2443
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2444
        goto cleanup;
2445 2446 2447 2448 2449 2450
    }


    if (!virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is not active"), pool->name);
2451
        goto cleanup;
2452 2453
    }

C
Cole Robinson 已提交
2454 2455
    for (i = 0 ; i < privpool->volumes.count && n < maxnames ; i++) {
        if ((names[n++] = strdup(privpool->volumes.objs[i]->name)) == NULL) {
2456
            testError(pool->conn, VIR_ERR_NO_MEMORY, "%s", _("name"));
C
Cole Robinson 已提交
2457 2458 2459 2460 2461 2462 2463 2464 2465 2466
            goto cleanup;
        }
    }

    return n;

 cleanup:
    for (n = 0 ; n < maxnames ; n++)
        VIR_FREE(names[i]);

2467
    memset(names, 0, maxnames * sizeof(*names));
C
Cole Robinson 已提交
2468 2469 2470 2471 2472
    return -1;
}


static virStorageVolPtr
2473
testStorageVolumeLookupByName(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2474
                              const char *name ATTRIBUTE_UNUSED) {
2475 2476 2477
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
2478
    virStorageVolPtr ret = NULL;
2479 2480 2481

    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
C
Cole Robinson 已提交
2482

2483 2484
    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2485
        goto cleanup;
2486 2487 2488 2489 2490 2491
    }


    if (!virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is not active"), pool->name);
2492
        goto cleanup;
2493 2494 2495 2496 2497 2498
    }

    privvol = virStorageVolDefFindByName(privpool, name);

    if (!privvol) {
        testError(pool->conn, VIR_ERR_INVALID_STORAGE_VOL,
C
Cole Robinson 已提交
2499
                  _("no storage vol with matching name '%s'"), name);
2500
        goto cleanup;
C
Cole Robinson 已提交
2501 2502
    }

2503 2504 2505 2506 2507
    ret = virGetStorageVol(pool->conn, privpool->def->name,
                           privvol->name, privvol->key);

cleanup:
    return ret;
C
Cole Robinson 已提交
2508 2509 2510 2511 2512 2513
}


static virStorageVolPtr
testStorageVolumeLookupByKey(virConnectPtr conn,
                             const char *key) {
2514
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
2515
    unsigned int i;
2516
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
2517 2518 2519

    for (i = 0 ; i < privconn->pools.count ; i++) {
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
2520
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
2521 2522
                virStorageVolDefFindByKey(privconn->pools.objs[i], key);

2523 2524 2525 2526 2527 2528 2529
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
                                       privvol->key);
                break;
            }
C
Cole Robinson 已提交
2530 2531 2532
        }
    }

2533 2534 2535 2536 2537
    if (!ret)
        testError(conn, VIR_ERR_INVALID_STORAGE_VOL,
                  _("no storage vol with matching key '%s'"), key);

    return ret;
C
Cole Robinson 已提交
2538 2539 2540 2541 2542
}

static virStorageVolPtr
testStorageVolumeLookupByPath(virConnectPtr conn,
                              const char *path) {
2543
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
2544
    unsigned int i;
2545
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
2546 2547 2548

    for (i = 0 ; i < privconn->pools.count ; i++) {
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
2549
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
2550 2551
                virStorageVolDefFindByPath(privconn->pools.objs[i], path);

2552 2553 2554 2555 2556 2557 2558
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
                                       privvol->key);
                break;
            }
C
Cole Robinson 已提交
2559 2560 2561
        }
    }

2562 2563 2564 2565 2566
    if (!ret)
        testError(conn, VIR_ERR_INVALID_STORAGE_VOL,
                  _("no storage vol with matching path '%s'"), path);

    return ret;
C
Cole Robinson 已提交
2567 2568 2569
}

static virStorageVolPtr
2570
testStorageVolumeCreateXML(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2571 2572
                           const char *xmldesc,
                           unsigned int flags ATTRIBUTE_UNUSED) {
2573 2574
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2575 2576
    virStorageVolDefPtr privvol = NULL;
    virStorageVolPtr ret = NULL;
2577 2578 2579

    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
C
Cole Robinson 已提交
2580

2581 2582
    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2583
        goto cleanup;
2584 2585 2586 2587 2588 2589
    }


    if (!virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is not active"), pool->name);
2590
        goto cleanup;
2591
    }
C
Cole Robinson 已提交
2592

2593 2594 2595

    privvol = virStorageVolDefParse(pool->conn, privpool->def, xmldesc, NULL);
    if (privvol == NULL)
2596
        goto cleanup;
2597 2598 2599

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
        testError(pool->conn, VIR_ERR_INVALID_STORAGE_POOL,
C
Cole Robinson 已提交
2600
                  "%s", _("storage vol already exists"));
2601
        goto cleanup;
C
Cole Robinson 已提交
2602 2603 2604
    }

    /* Make sure enough space */
2605
    if ((privpool->def->allocation + privvol->allocation) >
C
Cole Robinson 已提交
2606
         privpool->def->capacity) {
2607
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
C
Cole Robinson 已提交
2608
                  _("Not enough free space in pool for volume '%s'"),
2609
                  privvol->name);
2610
        goto cleanup;
C
Cole Robinson 已提交
2611 2612 2613 2614 2615 2616
    }
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    if (VIR_REALLOC_N(privpool->volumes.objs,
                      privpool->volumes.count+1) < 0) {
2617
        testError(pool->conn, VIR_ERR_NO_MEMORY, NULL);
2618
        goto cleanup;
C
Cole Robinson 已提交
2619 2620
    }

2621 2622 2623 2624
    if (VIR_ALLOC_N(privvol->target.path,
                    strlen(privpool->def->target.path) +
                    1 + strlen(privvol->name) + 1) < 0) {
        testError(pool->conn, VIR_ERR_NO_MEMORY, "%s", _("target"));
2625
        goto cleanup;
C
Cole Robinson 已提交
2626 2627
    }

2628 2629 2630 2631 2632 2633
    strcpy(privvol->target.path, privpool->def->target.path);
    strcat(privvol->target.path, "/");
    strcat(privvol->target.path, privvol->name);
    privvol->key = strdup(privvol->target.path);
    if (privvol->key == NULL) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR, "%s",
C
Cole Robinson 已提交
2634
                  _("storage vol key"));
2635
        goto cleanup;
C
Cole Robinson 已提交
2636 2637
    }

2638
    privpool->def->allocation += privvol->allocation;
C
Cole Robinson 已提交
2639 2640 2641
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

2642
    privpool->volumes.objs[privpool->volumes.count++] = privvol;
2643
    privvol = NULL;
C
Cole Robinson 已提交
2644

2645 2646 2647 2648 2649 2650
    ret = virGetStorageVol(pool->conn, privpool->def->name,
                           privvol->name, privvol->key);

cleanup:
    virStorageVolDefFree(privvol);
    return ret;
C
Cole Robinson 已提交
2651 2652 2653
}

static int
2654
testStorageVolumeDelete(virStorageVolPtr vol,
C
Cole Robinson 已提交
2655
                        unsigned int flags ATTRIBUTE_UNUSED) {
2656 2657 2658
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
C
Cole Robinson 已提交
2659
    int i;
2660
    int ret = -1;
C
Cole Robinson 已提交
2661

2662 2663 2664 2665 2666
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);

    if (privpool == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2667
        goto cleanup;
2668 2669 2670 2671 2672 2673 2674 2675 2676
    }


    privvol = virStorageVolDefFindByName(privpool, vol->name);

    if (privvol == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL,
                  _("no storage vol with matching name '%s'"),
                  vol->name);
2677
        goto cleanup;
2678 2679 2680 2681 2682
    }

    if (!virStoragePoolObjIsActive(privpool)) {
        testError(vol->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is not active"), vol->pool);
2683
        goto cleanup;
2684 2685 2686
    }


C
Cole Robinson 已提交
2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709
    privpool->def->allocation -= privvol->allocation;
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    for (i = 0 ; i < privpool->volumes.count ; i++) {
        if (privpool->volumes.objs[i] == privvol) {
            virStorageVolDefFree(privvol);

            if (i < (privpool->volumes.count - 1))
                memmove(privpool->volumes.objs + i,
                        privpool->volumes.objs + i + 1,
                        sizeof(*(privpool->volumes.objs)) *
                                (privpool->volumes.count - (i + 1)));

            if (VIR_REALLOC_N(privpool->volumes.objs,
                              privpool->volumes.count - 1) < 0) {
                ; /* Failure to reduce memory allocation isn't fatal */
            }
            privpool->volumes.count--;

            break;
        }
    }
2710
    ret = 0;
C
Cole Robinson 已提交
2711

2712 2713
cleanup:
    return ret;
C
Cole Robinson 已提交
2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729
}


static int testStorageVolumeTypeForPool(int pooltype) {

    switch(pooltype) {
        case VIR_STORAGE_POOL_DIR:
        case VIR_STORAGE_POOL_FS:
        case VIR_STORAGE_POOL_NETFS:
            return VIR_STORAGE_VOL_FILE;
        default:
            return VIR_STORAGE_VOL_BLOCK;
    }
}

static int
2730
testStorageVolumeGetInfo(virStorageVolPtr vol,
C
Cole Robinson 已提交
2731
                         virStorageVolInfoPtr info) {
2732 2733 2734
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
2735
    int ret = -1;
2736 2737 2738 2739 2740 2741

    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);

    if (privpool == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2742
        goto cleanup;
2743 2744 2745 2746 2747 2748 2749 2750
    }

    privvol = virStorageVolDefFindByName(privpool, vol->name);

    if (privvol == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL,
                  _("no storage vol with matching name '%s'"),
                  vol->name);
2751
        goto cleanup;
2752 2753 2754 2755 2756
    }

    if (!virStoragePoolObjIsActive(privpool)) {
        testError(vol->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is not active"), vol->pool);
2757
        goto cleanup;
2758
    }
C
Cole Robinson 已提交
2759 2760 2761 2762 2763

    memset(info, 0, sizeof(*info));
    info->type = testStorageVolumeTypeForPool(privpool->def->type);
    info->capacity = privvol->capacity;
    info->allocation = privvol->allocation;
2764
    ret = 0;
C
Cole Robinson 已提交
2765

2766 2767
cleanup:
    return ret;
C
Cole Robinson 已提交
2768 2769 2770
}

static char *
2771
testStorageVolumeGetXMLDesc(virStorageVolPtr vol,
C
Cole Robinson 已提交
2772
                            unsigned int flags ATTRIBUTE_UNUSED) {
2773 2774 2775
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
2776
    char *ret = NULL;
2777 2778 2779 2780 2781 2782

    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);

    if (privpool == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2783
        goto cleanup;
2784 2785 2786 2787 2788 2789 2790 2791
    }

    privvol = virStorageVolDefFindByName(privpool, vol->name);

    if (privvol == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL,
                  _("no storage vol with matching name '%s'"),
                  vol->name);
2792
        goto cleanup;
2793
    }
C
Cole Robinson 已提交
2794

2795 2796 2797
    if (!virStoragePoolObjIsActive(privpool)) {
        testError(vol->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is not active"), vol->pool);
2798
        goto cleanup;
2799 2800
    }

2801 2802 2803 2804
    ret = virStorageVolDefFormat(vol->conn, privpool->def, privvol);

cleanup:
    return ret;
C
Cole Robinson 已提交
2805 2806 2807
}

static char *
2808 2809 2810 2811
testStorageVolumeGetPath(virStorageVolPtr vol) {
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
2812
    char *ret = NULL;
2813 2814 2815 2816 2817 2818

    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);

    if (privpool == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2819
        goto cleanup;
2820 2821 2822 2823 2824 2825 2826 2827
    }

    privvol = virStorageVolDefFindByName(privpool, vol->name);

    if (privvol == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL,
                  _("no storage vol with matching name '%s'"),
                  vol->name);
2828
        goto cleanup;
2829 2830 2831 2832 2833
    }

    if (!virStoragePoolObjIsActive(privpool)) {
        testError(vol->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is not active"), vol->pool);
2834
        goto cleanup;
2835 2836
    }

C
Cole Robinson 已提交
2837
    ret = strdup(privvol->target.path);
2838
    if (ret == NULL)
2839
        testError(vol->conn, VIR_ERR_NO_MEMORY, "%s", _("path"));
2840 2841

cleanup:
C
Cole Robinson 已提交
2842 2843 2844
    return ret;
}

2845 2846 2847 2848 2849 2850

static virDriver testDriver = {
    VIR_DRV_TEST,
    "Test",
    testOpen, /* open */
    testClose, /* close */
2851
    NULL, /* supports_feature */
2852 2853 2854
    NULL, /* type */
    testGetVersion, /* version */
    testGetHostname, /* hostname */
2855
    NULL, /* URI */
2856 2857 2858 2859 2860
    testGetMaxVCPUs, /* getMaxVcpus */
    testNodeGetInfo, /* nodeGetInfo */
    testGetCapabilities, /* getCapabilities */
    testListDomains, /* listDomains */
    testNumOfDomains, /* numOfDomains */
2861
    testDomainCreateXML, /* domainCreateXML */
2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894
    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 */
2895 2896 2897
    NULL, /* domainMigratePrepare */
    NULL, /* domainMigratePerform */
    NULL, /* domainMigrateFinish */
2898 2899
    NULL, /* domainBlockStats */
    NULL, /* domainInterfaceStats */
R
Richard W.M. Jones 已提交
2900
    NULL, /* domainBlockPeek */
R
Richard W.M. Jones 已提交
2901
    NULL, /* domainMemoryPeek */
2902
    testNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
2903
    NULL, /* getFreeMemory */
2904 2905
    NULL, /* domainEventRegister */
    NULL, /* domainEventDeregister */
D
Daniel Veillard 已提交
2906 2907
    NULL, /* domainMigratePrepare2 */
    NULL, /* domainMigrateFinish2 */
2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930
};

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 */
};

2931 2932 2933 2934
static virStorageDriver testStorageDriver = {
    .name = "Test",
    .open = testStorageOpen,
    .close = testStorageClose,
C
Cole Robinson 已提交
2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966

    .numOfPools = testStorageNumPools,
    .listPools = testStorageListPools,
    .numOfDefinedPools = testStorageNumDefinedPools,
    .listDefinedPools = testStorageListDefinedPools,
    .findPoolSources = testStorageFindPoolSources,
    .poolLookupByName = testStoragePoolLookupByName,
    .poolLookupByUUID = testStoragePoolLookupByUUID,
    .poolLookupByVolume = testStoragePoolLookupByVolume,
    .poolCreateXML = testStoragePoolCreate,
    .poolDefineXML = testStoragePoolDefine,
    .poolBuild = testStoragePoolBuild,
    .poolUndefine = testStoragePoolUndefine,
    .poolCreate = testStoragePoolStart,
    .poolDestroy = testStoragePoolDestroy,
    .poolDelete = testStoragePoolDelete,
    .poolRefresh = testStoragePoolRefresh,
    .poolGetInfo = testStoragePoolGetInfo,
    .poolGetXMLDesc = testStoragePoolDumpXML,
    .poolGetAutostart = testStoragePoolGetAutostart,
    .poolSetAutostart = testStoragePoolSetAutostart,
    .poolNumOfVolumes = testStoragePoolNumVolumes,
    .poolListVolumes = testStoragePoolListVolumes,

    .volLookupByName = testStorageVolumeLookupByName,
    .volLookupByKey = testStorageVolumeLookupByKey,
    .volLookupByPath = testStorageVolumeLookupByPath,
    .volCreateXML = testStorageVolumeCreateXML,
    .volDelete = testStorageVolumeDelete,
    .volGetInfo = testStorageVolumeGetInfo,
    .volGetXMLDesc = testStorageVolumeGetXMLDesc,
    .volGetPath = testStorageVolumeGetPath,
2967 2968
};

2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
    if (virRegisterDriver(&testDriver) < 0)
        return -1;
    if (virRegisterNetworkDriver(&testNetworkDriver) < 0)
        return -1;
2981 2982
    if (virRegisterStorageDriver(&testStorageDriver) < 0)
        return -1;
2983 2984
    return 0;
}