test.c 105.0 KB
Newer Older
1 2 3
/*
 * test.c: A "mock" hypervisor for use by application unit tests
 *
4
 * Copyright (C) 2006-2009 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"
45 46
#include "domain_event.h"
#include "event.h"
C
Cole Robinson 已提交
47
#include "storage_conf.h"
48
#include "xml.h"
49
#include "threads.h"
50
#include "logging.h"
51

52 53
#define VIR_FROM_THIS VIR_FROM_TEST

54 55 56 57 58 59 60 61 62 63 64
#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
65

66
struct _testConn {
67
    virMutex lock;
68

69 70
    char path[PATH_MAX];
    int nextDomID;
71
    virCapsPtr caps;
72
    virNodeInfo nodeInfo;
73
    virDomainObjList domains;
74
    virNetworkObjList networks;
C
Cole Robinson 已提交
75
    virStoragePoolObjList pools;
76 77
    int numCells;
    testCell cells[MAX_CELLS];
78 79 80 81 82 83 84


    /* An array of callbacks */
    virDomainEventCallbackListPtr domainEventCallbacks;
    virDomainEventQueuePtr domainEventQueue;
    int domainEventTimer;
    int domainEventDispatching;
85 86 87
};
typedef struct _testConn testConn;
typedef struct _testConn *testConnPtr;
88

89
#define TEST_MODEL "i686"
90
#define TEST_MODEL_WORDSIZE 32
91
#define TEST_EMULATOR "/usr/bin/test-hv"
92

93
static const virNodeInfo defaultNodeInfo = {
94
    TEST_MODEL,
95 96 97 98 99 100 101
    1024*1024*3, /* 3 GB */
    16,
    1400,
    2,
    2,
    2,
    2,
102 103
};

104

105
#define testError(conn, code, fmt...)                               \
106
        virReportErrorHelper(conn, VIR_FROM_TEST, code, __FILE__, \
107
                               __FUNCTION__, __LINE__, fmt)
108

109 110 111 112 113 114
static int testClose(virConnectPtr conn);
static void testDomainEventFlush(int timer, void *opaque);
static void testDomainEventQueue(testConnPtr driver,
                                 virDomainEventPtr event);


115 116
static void testDriverLock(testConnPtr driver)
{
117
    virMutexLock(&driver->lock);
118 119 120 121
}

static void testDriverUnlock(testConnPtr driver)
{
122
    virMutexUnlock(&driver->lock);
123 124
}

125 126
static virCapsPtr
testBuildCapabilities(virConnectPtr conn) {
127
    testConnPtr privconn = conn->privateData;
128 129 130 131
    virCapsPtr caps;
    virCapsGuestPtr guest;
    const char *const guest_types[] = { "hvm", "xen" };
    int i;
132

133 134
    if ((caps = virCapabilitiesNew(TEST_MODEL, 0, 0)) == NULL)
        goto no_memory;
135

136 137 138 139
    if (virCapabilitiesAddHostFeature(caps, "pae") < 0)
        goto no_memory;
    if (virCapabilitiesAddHostFeature(caps ,"nonpae") < 0)
        goto no_memory;
140

141 142 143 144
    for (i = 0; i < privconn->numCells; i++) {
        if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].numCpus,
                                           privconn->cells[i].cpus) < 0)
            goto no_memory;
145 146
    }

147 148 149 150 151 152 153 154 155 156
    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;
157

158 159 160 161 162 163 164
        if (virCapabilitiesAddGuestDomain(guest,
                                          "test",
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
            goto no_memory;
165

166 167 168 169
        if (virCapabilitiesAddGuestFeature(guest, "pae", 1, 1) == NULL)
            goto no_memory;
        if (virCapabilitiesAddGuestFeature(guest ,"nonpae", 1, 1) == NULL)
            goto no_memory;
170 171
    }

172
    return caps;
173

174
no_memory:
175
    virReportOOMError(conn);
176 177
    virCapabilitiesFree(caps);
    return NULL;
178 179
}

180

181 182 183 184 185 186 187 188 189 190
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>";
191 192


193 194 195 196 197 198 199 200 201 202 203
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>";
204

C
Cole Robinson 已提交
205 206 207 208 209 210 211 212
static const char *defaultPoolXML =
"<pool type='dir'>"
"  <name>default-pool</name>"
"  <target>"
"    <path>/default-pool</path>"
"  </target>"
"</pool>";

213
static const unsigned long long defaultPoolCap = (100 * 1024 * 1024 * 1024ull);
C
Cole Robinson 已提交
214 215
static const unsigned long long defaultPoolAlloc = 0;

216
static int testStoragePoolObjSetDefaults(virConnectPtr conn, virStoragePoolObjPtr pool);
217

218
static int testOpenDefault(virConnectPtr conn) {
219 220
    int u;
    struct timeval tv;
221
    testConnPtr privconn;
222 223 224 225
    virDomainDefPtr domdef = NULL;
    virDomainObjPtr domobj = NULL;
    virNetworkDefPtr netdef = NULL;
    virNetworkObjPtr netobj = NULL;
C
Cole Robinson 已提交
226 227
    virStoragePoolDefPtr pooldef = NULL;
    virStoragePoolObjPtr poolobj = NULL;
228

229
    if (VIR_ALLOC(privconn) < 0) {
230
        virReportOOMError(conn);
231 232
        return VIR_DRV_OPEN_ERROR;
    }
233 234 235 236 237 238 239
    if (virMutexInit(&privconn->lock) < 0) {
        testError(conn, VIR_ERR_INTERNAL_ERROR,
                  "%s", _("cannot initialize mutex"));
        VIR_FREE(privconn);
        return VIR_DRV_OPEN_ERROR;
    }

240
    testDriverLock(privconn);
241
    conn->privateData = privconn;
242 243

    if (gettimeofday(&tv, NULL) < 0) {
244 245
        virReportSystemError(conn, errno,
                             "%s", _("getting time of day"));
246
        goto error;
247 248
    }

249
    memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));
250

251 252 253 254 255 256 257 258 259 260
    // 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;
    }

261 262 263 264 265
    if (!(privconn->caps = testBuildCapabilities(conn)))
        goto error;

    privconn->nextDomID = 1;

266 267 268
    if (!(domdef = virDomainDefParseString(conn, privconn->caps,
                                           defaultDomainXML,
                                           VIR_DOMAIN_XML_INACTIVE)))
269 270 271 272 273
        goto error;
    if (!(domobj = virDomainAssignDef(conn, &privconn->domains, domdef))) {
        virDomainDefFree(domdef);
        goto error;
    }
274
    domobj->def->id = privconn->nextDomID++;
275 276
    domobj->state = VIR_DOMAIN_RUNNING;
    domobj->persistent = 1;
277
    virDomainObjUnlock(domobj);
278 279 280 281 282 283 284 285 286

    if (!(netdef = virNetworkDefParseString(conn, defaultNetworkXML)))
        goto error;
    if (!(netobj = virNetworkAssignDef(conn, &privconn->networks, netdef))) {
        virNetworkDefFree(netdef);
        goto error;
    }
    netobj->active = 1;
    netobj->persistent = 1;
287
    virNetworkObjUnlock(netobj);
288

C
Cole Robinson 已提交
289 290 291 292 293 294 295 296
    if (!(pooldef = virStoragePoolDefParse(conn, defaultPoolXML, NULL)))
        goto error;

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

298
    if (testStoragePoolObjSetDefaults(conn, poolobj) == -1) {
299
        virStoragePoolObjUnlock(poolobj);
C
Cole Robinson 已提交
300
        goto error;
301
    }
C
Cole Robinson 已提交
302
    poolobj->active = 1;
303
    virStoragePoolObjUnlock(poolobj);
C
Cole Robinson 已提交
304

305
    testDriverUnlock(privconn);
306

307 308 309
    return VIR_DRV_OPEN_SUCCESS;

error:
310
    virDomainObjListFree(&privconn->domains);
311
    virNetworkObjListFree(&privconn->networks);
C
Cole Robinson 已提交
312
    virStoragePoolObjListFree(&privconn->pools);
313
    virCapabilitiesFree(privconn->caps);
314
    testDriverUnlock(privconn);
315
    conn->privateData = NULL;
316 317
    VIR_FREE(privconn);
    return VIR_DRV_OPEN_ERROR;
318 319 320 321
}


static char *testBuildFilename(const char *relativeTo,
322 323 324 325 326 327 328 329
                               const char *filename) {
    char *offset;
    int baseLen;
    if (!filename || filename[0] == '\0')
        return (NULL);
    if (filename[0] == '/')
        return strdup(filename);

330
    offset = strrchr(relativeTo, '/');
331
    if ((baseLen = (offset-relativeTo+1))) {
332 333 334
        char *absFile;
        if (VIR_ALLOC_N(absFile, baseLen + strlen(filename) + 1) < 0)
            return NULL;
335 336 337 338 339 340 341
        strncpy(absFile, relativeTo, baseLen);
        absFile[baseLen] = '\0';
        strcat(absFile, filename);
        return absFile;
    } else {
        return strdup(filename);
    }
342 343 344
}

static int testOpenFromFile(virConnectPtr conn,
345
                            const char *file) {
346
    int fd = -1, i, ret;
347 348
    long l;
    char *str;
349
    xmlDocPtr xml = NULL;
350
    xmlNodePtr root = NULL;
C
Cole Robinson 已提交
351
    xmlNodePtr *domains = NULL, *networks = NULL, *pools = NULL;
352 353
    xmlXPathContextPtr ctxt = NULL;
    virNodeInfoPtr nodeInfo;
354 355
    virNetworkObjPtr net;
    virDomainObjPtr dom;
356 357
    testConnPtr privconn;
    if (VIR_ALLOC(privconn) < 0) {
358
        virReportOOMError(conn);
359 360
        return VIR_DRV_OPEN_ERROR;
    }
361 362 363 364 365 366 367
    if (virMutexInit(&privconn->lock) < 0) {
        testError(conn, VIR_ERR_INTERNAL_ERROR,
                  "%s", _("cannot initialize mutex"));
        VIR_FREE(privconn);
        return VIR_DRV_OPEN_ERROR;
    }

368
    testDriverLock(privconn);
369
    conn->privateData = privconn;
370 371 372

    if (!(privconn->caps = testBuildCapabilities(conn)))
        goto error;
373 374

    if ((fd = open(file, O_RDONLY)) < 0) {
375 376 377
        virReportSystemError(NULL, errno,
                             _("loading host definition file '%s'"),
                             file);
378
        goto error;
379 380
    }

381 382 383
    if (!(xml = xmlReadFd(fd, file, NULL,
                          XML_PARSE_NOENT | XML_PARSE_NONET |
                          XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
J
Jim Meyering 已提交
384
        testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("host"));
385
        goto error;
386
    }
387 388
    close(fd);
    fd = -1;
389

390 391
    root = xmlDocGetRootElement(xml);
    if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "node"))) {
J
Jim Meyering 已提交
392
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node"));
393
        goto error;
394 395
    }

396 397
    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
C
Cole Robinson 已提交
398 399
        testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s",
                  _("creating xpath context"));
400
        goto error;
401
    }
402

403
    privconn->nextDomID = 1;
404
    privconn->numCells = 0;
405 406 407 408 409
    strncpy(privconn->path, file, PATH_MAX-1);
    privconn->path[PATH_MAX-1] = '\0';
    memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));

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

418
    ret = virXPathLong(conn, "string(/node/cpu/sockets[1])", ctxt, &l);
419 420 421
    if (ret == 0) {
        nodeInfo->sockets = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
422
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu sockets"));
423
        goto error;
424
    }
425

426
    ret = virXPathLong(conn, "string(/node/cpu/cores[1])", ctxt, &l);
427 428 429
    if (ret == 0) {
        nodeInfo->cores = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
430
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu cores"));
431
        goto error;
432 433
    }

434
    ret = virXPathLong(conn, "string(/node/cpu/threads[1])", ctxt, &l);
435 436 437
    if (ret == 0) {
        nodeInfo->threads = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
438
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu threads"));
439
        goto error;
440
    }
441

442
    nodeInfo->cpus = nodeInfo->cores * nodeInfo->threads * nodeInfo->sockets * nodeInfo->nodes;
443
    ret = virXPathLong(conn, "string(/node/cpu/active[1])", ctxt, &l);
444 445
    if (ret == 0) {
        if (l < nodeInfo->cpus) {
446 447
            nodeInfo->cpus = l;
        }
448
    } else if (ret == -2) {
J
Jim Meyering 已提交
449
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node active cpu"));
450
        goto error;
451
    }
452
    ret = virXPathLong(conn, "string(/node/cpu/mhz[1])", ctxt, &l);
453 454 455
    if (ret == 0) {
        nodeInfo->mhz = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
456
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu mhz"));
457
        goto error;
458 459
    }

460
    str = virXPathString(conn, "string(/node/cpu/model[1])", ctxt);
461 462
    if (str != NULL) {
        strncpy(nodeInfo->model, str, sizeof(nodeInfo->model)-1);
463
        nodeInfo->model[sizeof(nodeInfo->model)-1] = '\0';
464
        VIR_FREE(str);
465 466
    }

467
    ret = virXPathLong(conn, "string(/node/memory[1])", ctxt, &l);
468 469 470
    if (ret == 0) {
        nodeInfo->memory = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
471
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node memory"));
472
        goto error;
473
    }
474

475
    ret = virXPathNodeSet(conn, "/node/domain", ctxt, &domains);
476
    if (ret < 0) {
J
Jim Meyering 已提交
477
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node domain list"));
478
        goto error;
479
    }
480

481
    for (i = 0 ; i < ret ; i++) {
482 483 484 485 486 487
        virDomainDefPtr def;
        char *relFile = virXMLPropString(domains[i], "file");
        if (relFile != NULL) {
            char *absFile = testBuildFilename(file, relFile);
            VIR_FREE(relFile);
            if (!absFile) {
J
Jim Meyering 已提交
488
                testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("resolving domain filename"));
489 490
                goto error;
            }
491 492
            def = virDomainDefParseFile(conn, privconn->caps, absFile,
                                        VIR_DOMAIN_XML_INACTIVE);
493
            VIR_FREE(absFile);
494 495 496
            if (!def)
                goto error;
        } else {
497 498
            if ((def = virDomainDefParseNode(conn, privconn->caps, xml, domains[i],
                                   VIR_DOMAIN_XML_INACTIVE)) == NULL)
499 500 501 502 503
                goto error;
        }

        if (!(dom = virDomainAssignDef(conn, &privconn->domains, def))) {
            virDomainDefFree(def);
504 505
            goto error;
        }
506 507 508 509

        dom->state = VIR_DOMAIN_RUNNING;
        dom->def->id = privconn->nextDomID++;
        dom->persistent = 1;
510
        virDomainObjUnlock(dom);
511
    }
512
    VIR_FREE(domains);
513

514
    ret = virXPathNodeSet(conn, "/node/network", ctxt, &networks);
515
    if (ret < 0) {
J
Jim Meyering 已提交
516
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node network list"));
517 518 519 520 521 522 523 524
        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);
525
            if (!absFile) {
J
Jim Meyering 已提交
526
                testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("resolving network filename"));
527 528
                goto error;
            }
529 530

            def = virNetworkDefParseFile(conn, absFile);
531
            VIR_FREE(absFile);
532 533 534 535 536
            if (!def)
                goto error;
        } else {
            if ((def = virNetworkDefParseNode(conn, xml, networks[i])) == NULL)
                goto error;
537
        }
538 539 540 541
        if (!(net = virNetworkAssignDef(conn, &privconn->networks,
                                        def))) {
            virNetworkDefFree(def);
            goto error;
542
        }
543
        net->persistent = 1;
544
        virNetworkObjUnlock(net);
545
    }
546
    VIR_FREE(networks);
547

C
Cole Robinson 已提交
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
    /* 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;
        }

593
        if (testStoragePoolObjSetDefaults(conn, pool) == -1) {
594
            virStoragePoolObjUnlock(pool);
C
Cole Robinson 已提交
595
            goto error;
596
        }
C
Cole Robinson 已提交
597
        pool->active = 1;
598
        virStoragePoolObjUnlock(pool);
C
Cole Robinson 已提交
599
    }
600
    VIR_FREE(pools);
C
Cole Robinson 已提交
601

J
Jim Meyering 已提交
602
    xmlXPathFreeContext(ctxt);
603
    xmlFreeDoc(xml);
604
    testDriverUnlock(privconn);
605

606
    return (0);
607 608

 error:
J
Jim Meyering 已提交
609
    xmlXPathFreeContext(ctxt);
610
    xmlFreeDoc(xml);
611 612
    VIR_FREE(domains);
    VIR_FREE(networks);
C
Cole Robinson 已提交
613
    VIR_FREE(pools);
614 615
    if (fd != -1)
        close(fd);
616
    virDomainObjListFree(&privconn->domains);
617
    virNetworkObjListFree(&privconn->networks);
C
Cole Robinson 已提交
618
    virStoragePoolObjListFree(&privconn->pools);
619
    testDriverUnlock(privconn);
620
    VIR_FREE(privconn);
621
    conn->privateData = NULL;
622
    return VIR_DRV_OPEN_ERROR;
623 624
}

625

626
static virDrvOpenStatus testOpen(virConnectPtr conn,
627
                    virConnectAuthPtr auth ATTRIBUTE_UNUSED,
628
                    int flags ATTRIBUTE_UNUSED)
629
{
630
    int ret;
631

632
    if (!conn->uri)
633
        return VIR_DRV_OPEN_DECLINED;
634

635
    if (!conn->uri->scheme || STRNEQ(conn->uri->scheme, "test"))
636
        return VIR_DRV_OPEN_DECLINED;
637

638
    /* Remote driver should handle these. */
639
    if (conn->uri->server)
640 641
        return VIR_DRV_OPEN_DECLINED;

642
    if (conn->uri->server)
643 644
        return VIR_DRV_OPEN_DECLINED;

645
    /* From this point on, the connection is for us. */
646 647 648
    if (!conn->uri->path
        || conn->uri->path[0] == '\0'
        || (conn->uri->path[0] == '/' && conn->uri->path[1] == '\0')) {
649
        testError (NULL, VIR_ERR_INVALID_ARG,
J
Jim Meyering 已提交
650
                   "%s", _("testOpen: supply a path or use test:///default"));
651 652
        return VIR_DRV_OPEN_ERROR;
    }
653

654
    if (STREQ(conn->uri->path, "/default"))
655 656
        ret = testOpenDefault(conn);
    else
657
        ret = testOpenFromFile(conn,
658
                               conn->uri->path);
659

660 661
    if (ret == VIR_DRV_OPEN_SUCCESS) {
        testConnPtr privconn = conn->privateData;
662
        testDriverLock(privconn);
663 664 665 666
        /* Init callback list */
        if (VIR_ALLOC(privconn->domainEventCallbacks) < 0 ||
            !(privconn->domainEventQueue = virDomainEventQueueNew())) {
            virReportOOMError(NULL);
667
            testDriverUnlock(privconn);
668 669 670 671 672 673 674 675
            testClose(conn);
            return VIR_DRV_OPEN_ERROR;
        }

        if ((privconn->domainEventTimer =
             virEventAddTimeout(-1, testDomainEventFlush, privconn, NULL)) < 0)
            DEBUG0("virEventAddTimeout failed: No addTimeoutImpl defined. "
                   "continuing without events.");
676
        testDriverUnlock(privconn);
677 678
    }

679
    return (ret);
680 681
}

682
static int testClose(virConnectPtr conn)
683
{
684
    testConnPtr privconn = conn->privateData;
685
    testDriverLock(privconn);
686
    virCapabilitiesFree(privconn->caps);
687
    virDomainObjListFree(&privconn->domains);
688
    virNetworkObjListFree(&privconn->networks);
C
Cole Robinson 已提交
689
    virStoragePoolObjListFree(&privconn->pools);
690 691 692 693 694 695 696

    virDomainEventCallbackListFree(privconn->domainEventCallbacks);
    virDomainEventQueueFree(privconn->domainEventQueue);

    if (privconn->domainEventTimer != -1)
        virEventRemoveTimeout(privconn->domainEventTimer);

697
    testDriverUnlock(privconn);
698
    virMutexDestroy(&privconn->lock);
699

700
    VIR_FREE (privconn);
701
    conn->privateData = NULL;
702
    return 0;
703 704
}

705 706
static int testGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
                          unsigned long *hvVer)
707
{
708 709
    *hvVer = 2;
    return (0);
710 711
}

712
static char *testGetHostname (virConnectPtr conn)
713
{
714
    char *result;
715

716 717
    result = virGetHostname();
    if (result == NULL) {
718 719
        virReportSystemError(conn, errno,
                             "%s", _("cannot lookup hostname"));
720 721
        return NULL;
    }
722 723
    /* Caller frees this string. */
    return result;
724 725
}

726 727 728 729 730 731 732 733
static int testGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED,
                           const char *type ATTRIBUTE_UNUSED)
{
    return 32;
}

static int testNodeGetInfo(virConnectPtr conn,
                           virNodeInfoPtr info)
734
{
735
    testConnPtr privconn = conn->privateData;
736
    testDriverLock(privconn);
737
    memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo));
738
    testDriverUnlock(privconn);
739
    return (0);
740 741
}

742
static char *testGetCapabilities (virConnectPtr conn)
743
{
744
    testConnPtr privconn = conn->privateData;
745
    char *xml;
746
    testDriverLock(privconn);
747
    if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL)
748
        virReportOOMError(conn);
749
    testDriverUnlock(privconn);
750
    return xml;
751 752
}

753
static int testNumOfDomains(virConnectPtr conn)
754
{
755
    testConnPtr privconn = conn->privateData;
756
    unsigned int numActive = 0, i;
757

758
    testDriverLock(privconn);
759 760
    for (i = 0 ; i < privconn->domains.count ; i++)
        if (virDomainIsActive(privconn->domains.objs[i]))
761
            numActive++;
762
    testDriverUnlock(privconn);
763

764
    return numActive;
765 766
}

767
static virDomainPtr
768
testDomainCreateXML(virConnectPtr conn, const char *xml,
769
                      unsigned int flags ATTRIBUTE_UNUSED)
770
{
771
    testConnPtr privconn = conn->privateData;
772
    virDomainPtr ret = NULL;
773
    virDomainDefPtr def;
774
    virDomainObjPtr dom = NULL;
775
    virDomainEventPtr event = NULL;
776

777
    testDriverLock(privconn);
778 779
    if ((def = virDomainDefParseString(conn, privconn->caps, xml,
                                       VIR_DOMAIN_XML_INACTIVE)) == NULL)
780
        goto cleanup;
781

782 783 784
    if ((dom = virDomainAssignDef(conn, &privconn->domains,
                                  def)) == NULL) {
        virDomainDefFree(def);
785
        goto cleanup;
786
    }
787 788
    dom->state = VIR_DOMAIN_RUNNING;
    dom->def->id = privconn->nextDomID++;
789

790 791 792 793
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);

794
    ret = virGetDomain(conn, def->name, def->uuid);
795 796 797 798
    if (ret)
        ret->id = def->id;

cleanup:
799 800
    if (dom)
        virDomainObjUnlock(dom);
801 802
    if (event)
        testDomainEventQueue(privconn, event);
803
    testDriverUnlock(privconn);
804
    return ret;
805 806 807
}


808 809
static virDomainPtr testLookupDomainByID(virConnectPtr conn,
                                         int id)
810
{
811
    testConnPtr privconn = conn->privateData;
812 813
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
814

815 816 817 818 819
    testDriverLock(privconn);
    dom = virDomainFindByID(&privconn->domains, id);
    testDriverUnlock(privconn);

    if (dom == NULL) {
820
        testError (conn, VIR_ERR_NO_DOMAIN, NULL);
821
        goto cleanup;
822 823
    }

824
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
825 826 827 828
    if (ret)
        ret->id = dom->def->id;

cleanup:
829 830
    if (dom)
        virDomainObjUnlock(dom);
831
    return ret;
832 833
}

834 835
static virDomainPtr testLookupDomainByUUID(virConnectPtr conn,
                                           const unsigned char *uuid)
836
{
837
    testConnPtr privconn = conn->privateData;
838 839
    virDomainPtr ret = NULL;
    virDomainObjPtr dom ;
840

841 842 843 844 845
    testDriverLock(privconn);
    dom = virDomainFindByUUID(&privconn->domains, uuid);
    testDriverUnlock(privconn);

    if (dom == NULL) {
846
        testError (conn, VIR_ERR_NO_DOMAIN, NULL);
847
        goto cleanup;
848
    }
849

850
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
851 852 853 854
    if (ret)
        ret->id = dom->def->id;

cleanup:
855 856
    if (dom)
        virDomainObjUnlock(dom);
857
    return ret;
858 859
}

860 861
static virDomainPtr testLookupDomainByName(virConnectPtr conn,
                                           const char *name)
862
{
863
    testConnPtr privconn = conn->privateData;
864 865
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
866

867 868 869 870 871
    testDriverLock(privconn);
    dom = virDomainFindByName(&privconn->domains, name);
    testDriverUnlock(privconn);

    if (dom == NULL) {
872
        testError (conn, VIR_ERR_NO_DOMAIN, NULL);
873
        goto cleanup;
874
    }
875

876
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
877 878 879 880
    if (ret)
        ret->id = dom->def->id;

cleanup:
881 882
    if (dom)
        virDomainObjUnlock(dom);
883
    return ret;
884 885
}

886 887 888
static int testListDomains (virConnectPtr conn,
                            int *ids,
                            int maxids)
889
{
890
    testConnPtr privconn = conn->privateData;
891
    unsigned int n = 0, i;
892

893 894 895
    testDriverLock(privconn);
    for (i = 0 ; i < privconn->domains.count && n < maxids ; i++) {
        virDomainObjLock(privconn->domains.objs[i]);
896 897
        if (virDomainIsActive(privconn->domains.objs[i]))
            ids[n++] = privconn->domains.objs[i]->def->id;
898 899 900
        virDomainObjUnlock(privconn->domains.objs[i]);
    }
    testDriverUnlock(privconn);
901

902
    return n;
903 904
}

905
static int testDestroyDomain (virDomainPtr domain)
906
{
907 908
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
909
    virDomainEventPtr event = NULL;
910
    int ret = -1;
911

912
    testDriverLock(privconn);
913 914 915 916 917
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
918
        goto cleanup;
919
    }
920

921
    privdom->state = VIR_DOMAIN_SHUTOFF;
922 923
    privdom->def->id = -1;
    domain->id = -1;
924 925 926
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
927 928 929
    if (!privdom->persistent) {
        virDomainRemoveInactive(&privconn->domains,
                                privdom);
930
        privdom = NULL;
931
    }
932

933

934 935
    ret = 0;
cleanup:
936 937
    if (privdom)
        virDomainObjUnlock(privdom);
938 939
    if (event)
        testDomainEventQueue(privconn, event);
940
    testDriverUnlock(privconn);
941
    return ret;
942 943
}

944
static int testResumeDomain (virDomainPtr domain)
945
{
946 947
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
948
    virDomainEventPtr event = NULL;
949
    int ret = -1;
950

951
    testDriverLock(privconn);
952 953
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
954
    testDriverUnlock(privconn);
955 956 957

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

961
    if (privdom->state != VIR_DOMAIN_PAUSED) {
962 963 964
        testError(domain->conn,
                  VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"),
                  domain->name);
965
        goto cleanup;
966
    }
967

968
    privdom->state = VIR_DOMAIN_RUNNING;
969 970 971
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_RESUMED,
                                     VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
972 973 974
    ret = 0;

cleanup:
975 976
    if (privdom)
        virDomainObjUnlock(privdom);
977 978 979 980 981
    if (event) {
        testDriverLock(privconn);
        testDomainEventQueue(privconn, event);
        testDriverUnlock(privconn);
    }
982
    return ret;
983 984
}

985
static int testPauseDomain (virDomainPtr domain)
986
{
987 988
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
989
    virDomainEventPtr event = NULL;
990
    int ret = -1;
991

992
    testDriverLock(privconn);
993 994
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
995
    testDriverUnlock(privconn);
996 997 998

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

1002 1003
    if (privdom->state == VIR_DOMAIN_SHUTOFF ||
        privdom->state == VIR_DOMAIN_PAUSED) {
1004 1005 1006
        testError(domain->conn,
                  VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"),
                  domain->name);
1007
        goto cleanup;
1008
    }
1009

1010
    privdom->state = VIR_DOMAIN_PAUSED;
1011 1012 1013
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_SUSPENDED,
                                     VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
1014 1015 1016
    ret = 0;

cleanup:
1017 1018
    if (privdom)
        virDomainObjUnlock(privdom);
1019 1020 1021 1022 1023 1024

    if (event) {
        testDriverLock(privconn);
        testDomainEventQueue(privconn, event);
        testDriverUnlock(privconn);
    }
1025
    return ret;
1026 1027
}

1028
static int testShutdownDomain (virDomainPtr domain)
1029
{
1030 1031
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1032
    virDomainEventPtr event = NULL;
1033
    int ret = -1;
1034

1035
    testDriverLock(privconn);
1036 1037 1038 1039 1040
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1041
        goto cleanup;
1042
    }
1043

1044
    if (privdom->state == VIR_DOMAIN_SHUTOFF) {
1045 1046
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("domain '%s' not running"), domain->name);
1047
        goto cleanup;
1048
    }
1049

1050
    privdom->state = VIR_DOMAIN_SHUTOFF;
1051
    domain->id = -1;
1052
    privdom->def->id = -1;
1053 1054 1055
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1056 1057 1058 1059 1060
    if (!privdom->persistent) {
        virDomainRemoveInactive(&privconn->domains,
                                privdom);
        privdom = NULL;
    }
1061
    ret = 0;
1062

1063
cleanup:
1064 1065
    if (privdom)
        virDomainObjUnlock(privdom);
1066 1067
    if (event)
        testDomainEventQueue(privconn, event);
1068
    testDriverUnlock(privconn);
1069
    return ret;
1070 1071 1072
}

/* Similar behaviour as shutdown */
1073 1074
static int testRebootDomain (virDomainPtr domain,
                             unsigned int action ATTRIBUTE_UNUSED)
1075
{
1076 1077
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1078
    virDomainEventPtr event = NULL;
1079
    int ret = -1;
1080

1081
    testDriverLock(privconn);
1082 1083 1084 1085 1086
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1087
        goto cleanup;
1088
    }
1089

1090 1091 1092 1093
    privdom->state = VIR_DOMAIN_SHUTDOWN;
    switch (privdom->def->onReboot) {
    case VIR_DOMAIN_LIFECYCLE_DESTROY:
        privdom->state = VIR_DOMAIN_SHUTOFF;
1094
        domain->id = -1;
1095
        privdom->def->id = -1;
1096 1097
        break;

1098 1099
    case VIR_DOMAIN_LIFECYCLE_RESTART:
        privdom->state = VIR_DOMAIN_RUNNING;
1100 1101
        break;

1102 1103
    case VIR_DOMAIN_LIFECYCLE_PRESERVE:
        privdom->state = VIR_DOMAIN_SHUTOFF;
1104
        domain->id = -1;
1105
        privdom->def->id = -1;
1106 1107
        break;

1108 1109
    case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME:
        privdom->state = VIR_DOMAIN_RUNNING;
1110
        break;
1111

1112
    default:
1113
        privdom->state = VIR_DOMAIN_SHUTOFF;
1114
        domain->id = -1;
1115
        privdom->def->id = -1;
1116 1117
        break;
    }
1118

1119 1120 1121 1122 1123 1124 1125 1126 1127
    if (privdom->state == VIR_DOMAIN_SHUTOFF) {
        event = virDomainEventNewFromObj(privdom,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
        if (!privdom->persistent) {
            virDomainRemoveInactive(&privconn->domains,
                                    privdom);
            privdom = NULL;
        }
1128 1129
    }

1130 1131 1132
    ret = 0;

cleanup:
1133 1134
    if (privdom)
        virDomainObjUnlock(privdom);
1135 1136
    if (event)
        testDomainEventQueue(privconn, event);
1137
    testDriverUnlock(privconn);
1138
    return ret;
1139 1140
}

1141 1142
static int testGetDomainInfo (virDomainPtr domain,
                              virDomainInfoPtr info)
1143
{
1144
    testConnPtr privconn = domain->conn->privateData;
1145
    struct timeval tv;
1146
    virDomainObjPtr privdom;
1147
    int ret = -1;
1148

1149
    testDriverLock(privconn);
1150 1151
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1152
    testDriverUnlock(privconn);
1153 1154 1155

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1156
        goto cleanup;
1157
    }
1158 1159

    if (gettimeofday(&tv, NULL) < 0) {
1160
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1161
                  "%s", _("getting time of day"));
1162
        goto cleanup;
1163 1164
    }

1165 1166 1167 1168 1169
    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));
1170 1171 1172
    ret = 0;

cleanup:
1173 1174
    if (privdom)
        virDomainObjUnlock(privdom);
1175
    return ret;
1176 1177
}

1178 1179 1180 1181 1182
#define TEST_SAVE_MAGIC "TestGuestMagic"

static int testDomainSave(virDomainPtr domain,
                          const char *path)
{
1183
    testConnPtr privconn = domain->conn->privateData;
1184 1185 1186
    char *xml = NULL;
    int fd = -1;
    int len;
1187
    virDomainObjPtr privdom;
1188
    virDomainEventPtr event = NULL;
1189
    int ret = -1;
1190

1191
    testDriverLock(privconn);
1192 1193 1194 1195 1196
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

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

C
Cole Robinson 已提交
1200 1201 1202 1203
    xml = virDomainDefFormat(domain->conn,
                             privdom->def,
                             VIR_DOMAIN_XML_SECURE);

1204
    if (xml == NULL) {
1205 1206 1207
        virReportSystemError(domain->conn, errno,
                             _("saving domain '%s' failed to allocate space for metadata"),
                             domain->name);
1208
        goto cleanup;
1209
    }
1210 1211

    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
1212 1213 1214
        virReportSystemError(domain->conn, errno,
                             _("saving domain '%s' to '%s': open failed"),
                             domain->name, path);
1215
        goto cleanup;
1216
    }
1217
    len = strlen(xml);
1218
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
1219 1220 1221
        virReportSystemError(domain->conn, errno,
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1222
        goto cleanup;
1223
    }
1224
    if (safewrite(fd, (char*)&len, sizeof(len)) < 0) {
1225 1226 1227
        virReportSystemError(domain->conn, errno,
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1228
        goto cleanup;
1229
    }
1230
    if (safewrite(fd, xml, len) < 0) {
1231 1232 1233
        virReportSystemError(domain->conn, errno,
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1234
        goto cleanup;
1235
    }
1236

1237
    if (close(fd) < 0) {
1238 1239 1240
        virReportSystemError(domain->conn, errno,
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1241
        goto cleanup;
1242
    }
1243 1244
    fd = -1;

1245
    privdom->state = VIR_DOMAIN_SHUTOFF;
1246 1247 1248
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
1249 1250 1251
    if (!privdom->persistent) {
        virDomainRemoveInactive(&privconn->domains,
                                privdom);
1252
        privdom = NULL;
1253
    }
1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266
    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);
    }
1267 1268
    if (privdom)
        virDomainObjUnlock(privdom);
1269 1270
    if (event)
        testDomainEventQueue(privconn, event);
1271
    testDriverUnlock(privconn);
1272
    return ret;
1273 1274
}

1275 1276
static int testDomainRestore(virConnectPtr conn,
                             const char *path)
1277
{
1278
    testConnPtr privconn = conn->privateData;
1279
    char *xml = NULL;
1280
    char magic[15];
1281 1282 1283
    int fd = -1;
    int len;
    virDomainDefPtr def = NULL;
1284
    virDomainObjPtr dom = NULL;
1285
    virDomainEventPtr event = NULL;
1286
    int ret = -1;
1287 1288

    if ((fd = open(path, O_RDONLY)) < 0) {
1289 1290 1291
        virReportSystemError(conn, errno,
                             _("cannot read domain image '%s'"),
                             path);
1292
        goto cleanup;
1293
    }
1294 1295 1296 1297
    if (saferead(fd, magic, sizeof(magic)) != sizeof(magic)) {
        virReportSystemError(conn, errno,
                             _("incomplete save header in '%s'"),
                             path);
1298
        goto cleanup;
1299
    }
1300
    if (memcmp(magic, TEST_SAVE_MAGIC, sizeof(magic))) {
1301
        testError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1302
                  "%s", _("mismatched header magic"));
1303
        goto cleanup;
1304
    }
1305 1306 1307 1308
    if (saferead(fd, (char*)&len, sizeof(len)) != sizeof(len)) {
        virReportSystemError(conn, errno,
                             _("failed to read metadata length in '%s'"),
                             path);
1309
        goto cleanup;
1310 1311
    }
    if (len < 1 || len > 8192) {
1312
        testError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1313
                  "%s", _("length of metadata out of range"));
1314
        goto cleanup;
1315
    }
1316
    if (VIR_ALLOC_N(xml, len+1) < 0) {
1317
        virReportOOMError(conn);
1318
        goto cleanup;
1319
    }
1320 1321 1322
    if (saferead(fd, xml, len) != len) {
        virReportSystemError(conn, errno,
                             _("incomplete metdata in '%s'"), path);
1323
        goto cleanup;
1324 1325
    }
    xml[len] = '\0';
1326

1327
    testDriverLock(privconn);
1328 1329
    def = virDomainDefParseString(conn, privconn->caps, xml,
                                  VIR_DOMAIN_XML_INACTIVE);
1330
    if (!def)
1331
        goto cleanup;
1332 1333

    if ((dom = virDomainAssignDef(conn, &privconn->domains,
1334 1335 1336
                                  def)) == NULL)
        goto cleanup;

1337 1338
    dom->state = VIR_DOMAIN_RUNNING;
    dom->def->id = privconn->nextDomID++;
1339
    def = NULL;
1340 1341 1342
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
1343
    ret = 0;
1344 1345 1346 1347 1348 1349

cleanup:
    virDomainDefFree(def);
    VIR_FREE(xml);
    if (fd != -1)
        close(fd);
1350 1351
    if (dom)
        virDomainObjUnlock(dom);
1352 1353
    if (event)
        testDomainEventQueue(privconn, event);
1354
    testDriverUnlock(privconn);
1355
    return ret;
1356 1357
}

1358 1359 1360
static int testDomainCoreDump(virDomainPtr domain,
                              const char *to,
                              int flags ATTRIBUTE_UNUSED)
1361
{
1362
    testConnPtr privconn = domain->conn->privateData;
1363
    int fd = -1;
1364
    virDomainObjPtr privdom;
1365
    virDomainEventPtr event = NULL;
1366
    int ret = -1;
1367

1368
    testDriverLock(privconn);
1369 1370 1371 1372 1373
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1374
        goto cleanup;
1375
    }
1376 1377

    if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
1378 1379 1380
        virReportSystemError(domain->conn, errno,
                             _("domain '%s' coredump: failed to open %s"),
                             domain->name, to);
1381
        goto cleanup;
1382
    }
1383
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
1384 1385 1386
        virReportSystemError(domain->conn, errno,
                             _("domain '%s' coredump: failed to write header to %s"),
                             domain->name, to);
1387
        goto cleanup;
1388
    }
1389
    if (close(fd) < 0) {
1390 1391 1392
        virReportSystemError(domain->conn, errno,
                             _("domain '%s' coredump: write failed: %s"),
                             domain->name, to);
1393
        goto cleanup;
1394
    }
1395
    privdom->state = VIR_DOMAIN_SHUTOFF;
1396 1397 1398
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_CRASHED);
1399 1400 1401
    if (!privdom->persistent) {
        virDomainRemoveInactive(&privconn->domains,
                                privdom);
1402
        privdom = NULL;
1403
    }
1404 1405 1406 1407 1408
    ret = 0;

cleanup:
    if (fd != -1)
        close(fd);
1409 1410
    if (privdom)
        virDomainObjUnlock(privdom);
1411 1412
    if (event)
        testDomainEventQueue(privconn, event);
1413
    testDriverUnlock(privconn);
1414
    return ret;
1415 1416
}

1417 1418 1419
static char *testGetOSType(virDomainPtr dom) {
    char *ret = strdup("linux");
    if (!ret)
1420
        virReportOOMError(dom->conn);
1421
    return ret;
1422 1423 1424
}

static unsigned long testGetMaxMemory(virDomainPtr domain) {
1425 1426
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1427
    unsigned long ret = 0;
1428

1429
    testDriverLock(privconn);
1430 1431
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1432
    testDriverUnlock(privconn);
1433 1434 1435

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1436
        goto cleanup;
1437
    }
1438

1439 1440 1441
    ret = privdom->def->maxmem;

cleanup:
1442 1443
    if (privdom)
        virDomainObjUnlock(privdom);
1444
    return ret;
1445 1446 1447 1448 1449
}

static int testSetMaxMemory(virDomainPtr domain,
                            unsigned long memory)
{
1450 1451
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1452
    int ret = -1;
1453

1454
    testDriverLock(privconn);
1455 1456
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1457
    testDriverUnlock(privconn);
1458 1459 1460

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

    /* XXX validate not over host memory wrt to other domains */
1465
    privdom->def->maxmem = memory;
1466 1467 1468
    ret = 0;

cleanup:
1469 1470
    if (privdom)
        virDomainObjUnlock(privdom);
1471
    return ret;
1472 1473
}

1474 1475 1476
static int testSetMemory(virDomainPtr domain,
                         unsigned long memory)
{
1477 1478
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1479
    int ret = -1;
1480

1481
    testDriverLock(privconn);
1482 1483
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1484
    testDriverUnlock(privconn);
1485 1486 1487

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1488
        goto cleanup;
1489
    }
1490

1491
    if (memory > privdom->def->maxmem) {
1492
        testError(domain->conn,
1493
                  VIR_ERR_INVALID_ARG, __FUNCTION__);
1494
        goto cleanup;
1495
    }
1496

1497
    privdom->def->memory = memory;
1498 1499 1500
    ret = 0;

cleanup:
1501 1502
    if (privdom)
        virDomainObjUnlock(privdom);
1503
    return ret;
1504 1505 1506 1507
}

static int testSetVcpus(virDomainPtr domain,
                        unsigned int nrCpus) {
1508 1509
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1510 1511
    int ret = -1;

1512 1513 1514 1515 1516 1517
    testDriverLock(privconn);
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
    testDriverUnlock(privconn);

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

1522 1523
    /* We allow more cpus in guest than host */
    if (nrCpus > 32) {
1524
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1525
        goto cleanup;
1526
    }
1527

1528
    privdom->def->vcpus = nrCpus;
1529 1530 1531
    ret = 0;

cleanup:
1532 1533
    if (privdom)
        virDomainObjUnlock(privdom);
1534
    return ret;
1535 1536
}

1537
static char *testDomainDumpXML(virDomainPtr domain, int flags)
1538
{
1539
    testConnPtr privconn = domain->conn->privateData;
1540
    virDomainDefPtr def;
1541
    virDomainObjPtr privdom;
1542 1543
    char *ret = NULL;

1544 1545 1546 1547 1548 1549
    testDriverLock(privconn);
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
    testDriverUnlock(privconn);

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

1554 1555
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
1556

1557 1558 1559 1560 1561
    ret = virDomainDefFormat(domain->conn,
                             def,
                             flags);

cleanup:
1562 1563
    if (privdom)
        virDomainObjUnlock(privdom);
1564
    return ret;
1565
}
1566

1567
static int testNumOfDefinedDomains(virConnectPtr conn) {
1568
    testConnPtr privconn = conn->privateData;
1569
    unsigned int numInactive = 0, i;
1570

1571 1572 1573
    testDriverLock(privconn);
    for (i = 0 ; i < privconn->domains.count ; i++) {
        virDomainObjLock(privconn->domains.objs[i]);
1574
        if (!virDomainIsActive(privconn->domains.objs[i]))
1575
            numInactive++;
1576 1577 1578
        virDomainObjUnlock(privconn->domains.objs[i]);
    }
    testDriverUnlock(privconn);
1579

1580
    return numInactive;
1581 1582
}

1583 1584 1585
static int testListDefinedDomains(virConnectPtr conn,
                                  char **const names,
                                  int maxnames) {
1586
    testConnPtr privconn = conn->privateData;
1587
    unsigned int n = 0, i;
1588

1589
    testDriverLock(privconn);
1590
    memset(names, 0, sizeof(*names)*maxnames);
1591 1592
    for (i = 0 ; i < privconn->domains.count && n < maxnames ; i++) {
        virDomainObjLock(privconn->domains.objs[i]);
1593
        if (!virDomainIsActive(privconn->domains.objs[i]) &&
1594 1595
            !(names[n++] = strdup(privconn->domains.objs[i]->def->name))) {
            virDomainObjUnlock(privconn->domains.objs[i]);
1596
            goto no_memory;
1597 1598 1599 1600
        }
        virDomainObjUnlock(privconn->domains.objs[i]);
    }
    testDriverUnlock(privconn);
1601

1602 1603 1604
    return n;

no_memory:
1605
    virReportOOMError(conn);
1606 1607
    for (n = 0 ; n < maxnames ; n++)
        VIR_FREE(names[n]);
1608
    testDriverUnlock(privconn);
1609
    return -1;
1610 1611
}

1612
static virDomainPtr testDomainDefineXML(virConnectPtr conn,
1613
                                        const char *xml) {
1614
    testConnPtr privconn = conn->privateData;
1615
    virDomainPtr ret = NULL;
1616
    virDomainDefPtr def;
1617
    virDomainObjPtr dom = NULL;
1618
    virDomainEventPtr event = NULL;
1619

1620
    testDriverLock(privconn);
1621 1622
    if ((def = virDomainDefParseString(conn, privconn->caps, xml,
                                       VIR_DOMAIN_XML_INACTIVE)) == NULL)
1623
        goto cleanup;
1624

1625 1626
    if ((dom = virDomainAssignDef(conn, &privconn->domains,
                                  def)) == NULL) {
1627
        goto cleanup;
1628 1629 1630
    }
    dom->persistent = 1;
    dom->def->id = -1;
1631 1632 1633
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_DEFINED,
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED);
1634

1635
    ret = virGetDomain(conn, def->name, def->uuid);
1636 1637 1638 1639 1640 1641
    def = NULL;
    if (ret)
        ret->id = -1;

cleanup:
    virDomainDefFree(def);
1642 1643
    if (dom)
        virDomainObjUnlock(dom);
1644 1645
    if (event)
        testDomainEventQueue(privconn, event);
1646
    testDriverUnlock(privconn);
1647
    return ret;
1648 1649
}

1650 1651 1652
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
                                      int startCell, int maxCells) {
1653
    testConnPtr privconn = conn->privateData;
1654
    int i, j;
1655
    int ret = -1;
1656

1657
    testDriverLock(privconn);
1658
    if (startCell > privconn->numCells) {
1659
        testError(conn, VIR_ERR_INVALID_ARG,
J
Jim Meyering 已提交
1660
                  "%s", _("Range exceeds available cells"));
1661
        goto cleanup;
1662 1663 1664 1665 1666 1667 1668
    }

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

1671
cleanup:
1672
    testDriverUnlock(privconn);
1673
    return ret;
1674 1675 1676
}


1677
static int testDomainCreate(virDomainPtr domain) {
1678 1679
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1680
    virDomainEventPtr event = NULL;
1681
    int ret = -1;
1682

1683
    testDriverLock(privconn);
1684 1685 1686 1687 1688
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1689
        goto cleanup;
1690
    }
1691

1692
    if (privdom->state != VIR_DOMAIN_SHUTOFF) {
1693 1694
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Domain '%s' is already running"), domain->name);
1695
        goto cleanup;
1696 1697
    }

1698 1699
    domain->id = privdom->def->id = privconn->nextDomID++;
    privdom->state = VIR_DOMAIN_RUNNING;
1700 1701 1702
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
1703
    ret = 0;
1704

1705
cleanup:
1706 1707
    if (privdom)
        virDomainObjUnlock(privdom);
1708 1709
    if (event)
        testDomainEventQueue(privconn, event);
1710
    testDriverUnlock(privconn);
1711
    return ret;
1712 1713 1714
}

static int testDomainUndefine(virDomainPtr domain) {
1715 1716
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1717
    virDomainEventPtr event = NULL;
1718
    int ret = -1;
1719

1720
    testDriverLock(privconn);
1721 1722 1723 1724 1725
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1726
        goto cleanup;
1727
    }
1728

1729
    if (privdom->state != VIR_DOMAIN_SHUTOFF) {
1730 1731
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Domain '%s' is still running"), domain->name);
1732
        goto cleanup;
1733 1734
    }

1735
    privdom->state = VIR_DOMAIN_SHUTOFF;
1736 1737 1738
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
1739 1740
    virDomainRemoveInactive(&privconn->domains,
                            privdom);
1741
    privdom = NULL;
1742
    ret = 0;
1743

1744
cleanup:
1745 1746
    if (privdom)
        virDomainObjUnlock(privdom);
1747 1748
    if (event)
        testDomainEventQueue(privconn, event);
1749
    testDriverUnlock(privconn);
1750
    return ret;
1751 1752
}

1753 1754 1755
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
1756 1757
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1758
    int ret = -1;
1759

1760
    testDriverLock(privconn);
1761 1762
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1763
    testDriverUnlock(privconn);
1764 1765 1766

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1767
        goto cleanup;
1768 1769
    }

1770
    *autostart = privdom->autostart;
1771 1772 1773
    ret = 0;

cleanup:
1774 1775
    if (privdom)
        virDomainObjUnlock(privdom);
1776
    return ret;
1777 1778 1779 1780 1781 1782
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
1783 1784
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1785
    int ret = -1;
1786

1787
    testDriverLock(privconn);
1788 1789
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1790
    testDriverUnlock(privconn);
1791 1792 1793

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1794
        goto cleanup;
1795 1796
    }

1797
    privdom->autostart = autostart ? 1 : 0;
1798 1799 1800
    ret = 0;

cleanup:
1801 1802
    if (privdom)
        virDomainObjUnlock(privdom);
1803
    return ret;
1804
}
1805

1806 1807 1808
static char *testDomainGetSchedulerType(virDomainPtr domain,
                                        int *nparams)
{
1809 1810
    char *type = NULL;

1811 1812
    *nparams = 1;
    type = strdup("fair");
1813
    if (!type)
1814
        virReportOOMError(domain->conn);
1815

1816 1817 1818 1819 1820 1821 1822
    return type;
}

static int testDomainGetSchedulerParams(virDomainPtr domain,
                                        virSchedParameterPtr params,
                                        int *nparams)
{
1823 1824
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1825
    int ret = -1;
1826

1827
    testDriverLock(privconn);
1828 1829
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1830
    testDriverUnlock(privconn);
1831 1832 1833

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1834
        goto cleanup;
1835 1836
    }

1837
    if (*nparams != 1) {
1838
        testError(domain->conn, VIR_ERR_INVALID_ARG, "nparams");
1839
        goto cleanup;
1840
    }
1841 1842
    strcpy(params[0].field, "weight");
    params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT;
1843 1844 1845
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
    params[0].value.ui = 50;
1846 1847 1848
    ret = 0;

cleanup:
1849 1850
    if (privdom)
        virDomainObjUnlock(privdom);
1851
    return ret;
1852
}
1853 1854


1855 1856 1857 1858
static int testDomainSetSchedulerParams(virDomainPtr domain,
                                        virSchedParameterPtr params,
                                        int nparams)
{
1859 1860
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1861
    int ret = -1;
1862

1863
    testDriverLock(privconn);
1864 1865
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1866
    testDriverUnlock(privconn);
1867 1868 1869

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1870
        goto cleanup;
1871 1872
    }

1873
    if (nparams != 1) {
1874
        testError(domain->conn, VIR_ERR_INVALID_ARG, "nparams");
1875
        goto cleanup;
1876
    }
1877
    if (STRNEQ(params[0].field, "weight")) {
1878
        testError(domain->conn, VIR_ERR_INVALID_ARG, "field");
1879
        goto cleanup;
1880 1881
    }
    if (params[0].type != VIR_DOMAIN_SCHED_FIELD_UINT) {
1882
        testError(domain->conn, VIR_ERR_INVALID_ARG, "type");
1883
        goto cleanup;
1884
    }
1885 1886
    /* XXX */
    /*privdom->weight = params[0].value.ui;*/
1887 1888 1889
    ret = 0;

cleanup:
1890 1891
    if (privdom)
        virDomainObjUnlock(privdom);
1892
    return ret;
1893 1894 1895
}

static virDrvOpenStatus testOpenNetwork(virConnectPtr conn,
1896
                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913
                                        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)
{
1914 1915
    testConnPtr privconn = conn->privateData;
    virNetworkObjPtr net;
1916
    virNetworkPtr ret = NULL;
1917

1918 1919 1920 1921 1922
    testDriverLock(privconn);
    net = virNetworkFindByUUID(&privconn->networks, uuid);
    testDriverUnlock(privconn);

    if (net == NULL) {
1923
        testError (conn, VIR_ERR_NO_NETWORK, NULL);
1924
        goto cleanup;
1925 1926
    }

1927 1928 1929
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

cleanup:
1930 1931
    if (net)
        virNetworkObjUnlock(net);
1932
    return ret;
1933
}
1934

1935
static virNetworkPtr testLookupNetworkByName(virConnectPtr conn,
1936
                                             const char *name)
1937
{
1938
    testConnPtr privconn = conn->privateData;
1939 1940
    virNetworkObjPtr net;
    virNetworkPtr ret = NULL;
1941

1942 1943 1944 1945 1946
    testDriverLock(privconn);
    net = virNetworkFindByName(&privconn->networks, name);
    testDriverUnlock(privconn);

    if (net == NULL) {
1947
        testError (conn, VIR_ERR_NO_NETWORK, NULL);
1948
        goto cleanup;
1949 1950
    }

1951 1952 1953
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

cleanup:
1954 1955
    if (net)
        virNetworkObjUnlock(net);
1956
    return ret;
1957 1958 1959 1960
}


static int testNumNetworks(virConnectPtr conn) {
1961
    testConnPtr privconn = conn->privateData;
1962
    int numActive = 0, i;
1963

1964 1965 1966
    testDriverLock(privconn);
    for (i = 0 ; i < privconn->networks.count ; i++) {
        virNetworkObjLock(privconn->networks.objs[i]);
1967
        if (virNetworkIsActive(privconn->networks.objs[i]))
1968
            numActive++;
1969 1970 1971
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
1972

1973
    return numActive;
1974 1975 1976
}

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

1980
    testDriverLock(privconn);
1981
    memset(names, 0, sizeof(*names)*nnames);
1982 1983
    for (i = 0 ; i < privconn->networks.count && n < nnames ; i++) {
        virNetworkObjLock(privconn->networks.objs[i]);
1984
        if (virNetworkIsActive(privconn->networks.objs[i]) &&
1985 1986
            !(names[n++] = strdup(privconn->networks.objs[i]->def->name))) {
            virNetworkObjUnlock(privconn->networks.objs[i]);
1987
            goto no_memory;
1988 1989 1990 1991
        }
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
1992

1993 1994 1995
    return n;

no_memory:
1996
    virReportOOMError(conn);
1997 1998
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
1999
    testDriverUnlock(privconn);
2000
    return -1;
2001 2002 2003
}

static int testNumDefinedNetworks(virConnectPtr conn) {
2004
    testConnPtr privconn = conn->privateData;
2005
    int numInactive = 0, i;
2006

2007 2008 2009
    testDriverLock(privconn);
    for (i = 0 ; i < privconn->networks.count ; i++) {
        virNetworkObjLock(privconn->networks.objs[i]);
2010
        if (!virNetworkIsActive(privconn->networks.objs[i]))
2011
            numInactive++;
2012 2013 2014
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
2015

2016
    return numInactive;
2017 2018 2019
}

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

2023
    testDriverLock(privconn);
2024
    memset(names, 0, sizeof(*names)*nnames);
2025 2026
    for (i = 0 ; i < privconn->networks.count && n < nnames ; i++) {
        virNetworkObjLock(privconn->networks.objs[i]);
2027
        if (!virNetworkIsActive(privconn->networks.objs[i]) &&
2028 2029
            !(names[n++] = strdup(privconn->networks.objs[i]->def->name))) {
            virNetworkObjUnlock(privconn->networks.objs[i]);
2030
            goto no_memory;
2031 2032 2033 2034
        }
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
2035

2036 2037 2038
    return n;

no_memory:
2039
    virReportOOMError(conn);
2040 2041
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
2042
    testDriverUnlock(privconn);
2043
    return -1;
2044 2045 2046
}

static virNetworkPtr testNetworkCreate(virConnectPtr conn, const char *xml) {
2047
    testConnPtr privconn = conn->privateData;
2048
    virNetworkDefPtr def;
2049
    virNetworkObjPtr net = NULL;
2050
    virNetworkPtr ret = NULL;
2051

2052
    testDriverLock(privconn);
2053
    if ((def = virNetworkDefParseString(conn, xml)) == NULL)
2054
        goto cleanup;
2055

2056
    if ((net = virNetworkAssignDef(conn, &privconn->networks, def)) == NULL)
2057 2058
        goto cleanup;
    def = NULL;
2059
    net->active = 1;
2060

2061
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
2062

2063 2064
cleanup:
    virNetworkDefFree(def);
2065 2066 2067
    if (net)
        virNetworkObjUnlock(net);
    testDriverUnlock(privconn);
2068
    return ret;
2069 2070 2071
}

static virNetworkPtr testNetworkDefine(virConnectPtr conn, const char *xml) {
2072
    testConnPtr privconn = conn->privateData;
2073
    virNetworkDefPtr def;
2074
    virNetworkObjPtr net = NULL;
2075
    virNetworkPtr ret = NULL;
2076

2077
    testDriverLock(privconn);
2078
    if ((def = virNetworkDefParseString(conn, xml)) == NULL)
2079
        goto cleanup;
2080

2081
    if ((net = virNetworkAssignDef(conn, &privconn->networks, def)) == NULL)
2082 2083
        goto cleanup;
    def = NULL;
2084
    net->persistent = 1;
2085

2086
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
2087 2088 2089

cleanup:
    virNetworkDefFree(def);
2090 2091 2092
    if (net)
        virNetworkObjUnlock(net);
    testDriverUnlock(privconn);
2093
    return ret;
2094 2095 2096
}

static int testNetworkUndefine(virNetworkPtr network) {
2097 2098
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
2099
    int ret = -1;
2100

2101
    testDriverLock(privconn);
2102 2103 2104 2105 2106
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2107
        goto cleanup;
2108
    }
2109

2110
    if (virNetworkIsActive(privnet)) {
2111 2112
        testError(network->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Network '%s' is still running"), network->name);
2113
        goto cleanup;
2114 2115
    }

2116 2117
    virNetworkRemoveInactive(&privconn->networks,
                             privnet);
2118
    privnet = NULL;
2119
    ret = 0;
2120

2121
cleanup:
2122 2123 2124
    if (privnet)
        virNetworkObjUnlock(privnet);
    testDriverUnlock(privconn);
2125
    return ret;
2126 2127 2128
}

static int testNetworkStart(virNetworkPtr network) {
2129 2130
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
2131
    int ret = -1;
2132

2133
    testDriverLock(privconn);
2134 2135
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
2136
    testDriverUnlock(privconn);
2137 2138 2139

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2140
        goto cleanup;
2141
    }
2142

2143
    if (virNetworkIsActive(privnet)) {
2144 2145
        testError(network->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Network '%s' is already running"), network->name);
2146
        goto cleanup;
2147 2148
    }

2149
    privnet->active = 1;
2150
    ret = 0;
2151

2152
cleanup:
2153 2154
    if (privnet)
        virNetworkObjUnlock(privnet);
2155
    return ret;
2156 2157 2158
}

static int testNetworkDestroy(virNetworkPtr network) {
2159 2160
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
2161
    int ret = -1;
2162

2163
    testDriverLock(privconn);
2164 2165 2166 2167 2168
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2169
        goto cleanup;
2170
    }
2171

2172 2173 2174 2175
    privnet->active = 0;
    if (!privnet->persistent) {
        virNetworkRemoveInactive(&privconn->networks,
                                 privnet);
2176
        privnet = NULL;
2177
    }
2178 2179 2180
    ret = 0;

cleanup:
2181 2182 2183
    if (privnet)
        virNetworkObjUnlock(privnet);
    testDriverUnlock(privconn);
2184
    return ret;
2185 2186 2187
}

static char *testNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) {
2188 2189
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
2190
    char *ret = NULL;
2191

2192
    testDriverLock(privconn);
2193 2194
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
2195
    testDriverUnlock(privconn);
2196 2197 2198

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2199
        goto cleanup;
2200
    }
2201

2202 2203 2204
    ret = virNetworkDefFormat(network->conn, privnet->def);

cleanup:
2205 2206
    if (privnet)
        virNetworkObjUnlock(privnet);
2207
    return ret;
2208 2209 2210
}

static char *testNetworkGetBridgeName(virNetworkPtr network) {
2211
    testConnPtr privconn = network->conn->privateData;
2212
    char *bridge = NULL;
2213 2214
    virNetworkObjPtr privnet;

2215
    testDriverLock(privconn);
2216 2217
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
2218
    testDriverUnlock(privconn);
2219 2220 2221

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2222
        goto cleanup;
2223 2224
    }

2225 2226
    if (privnet->def->bridge &&
        !(bridge = strdup(privnet->def->bridge))) {
2227
        virReportOOMError(network->conn);
2228
        goto cleanup;
2229
    }
2230 2231

cleanup:
2232 2233
    if (privnet)
        virNetworkObjUnlock(privnet);
2234 2235 2236 2237 2238
    return bridge;
}

static int testNetworkGetAutostart(virNetworkPtr network,
                                   int *autostart) {
2239 2240
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
2241
    int ret = -1;
2242

2243
    testDriverLock(privconn);
2244 2245
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
2246
    testDriverUnlock(privconn);
2247 2248 2249

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2250
        goto cleanup;
2251 2252
    }

2253
    *autostart = privnet->autostart;
2254 2255 2256
    ret = 0;

cleanup:
2257 2258
    if (privnet)
        virNetworkObjUnlock(privnet);
2259
    return ret;
2260 2261 2262 2263
}

static int testNetworkSetAutostart(virNetworkPtr network,
                                   int autostart) {
2264 2265
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
2266
    int ret = -1;
2267

2268
    testDriverLock(privconn);
2269 2270
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
2271
    testDriverUnlock(privconn);
2272 2273 2274

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2275
        goto cleanup;
2276 2277
    }

2278
    privnet->autostart = autostart ? 1 : 0;
2279 2280 2281
    ret = 0;

cleanup:
2282 2283
    if (privnet)
        virNetworkObjUnlock(privnet);
2284
    return ret;
2285
}
2286

C
Cole Robinson 已提交
2287 2288 2289 2290 2291

/*
 * Storage Driver routines
 */

2292 2293
static int testStoragePoolObjSetDefaults(virConnectPtr conn,
                                         virStoragePoolObjPtr pool) {
C
Cole Robinson 已提交
2294 2295 2296 2297 2298 2299 2300

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

    pool->configFile = strdup("\0");
    if (!pool->configFile) {
2301
        virReportOOMError(conn);
C
Cole Robinson 已提交
2302 2303 2304 2305 2306 2307
        return -1;
    }

    return 0;
}

2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322
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 已提交
2323 2324 2325
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
                            const unsigned char *uuid) {
2326
    testConnPtr privconn = conn->privateData;
2327 2328
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
2329

2330
    testDriverLock(privconn);
2331
    pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid);
2332
    testDriverUnlock(privconn);
2333 2334

    if (pool == NULL) {
C
Cole Robinson 已提交
2335
        testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL);
2336
        goto cleanup;
C
Cole Robinson 已提交
2337 2338
    }

2339 2340 2341
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
2342 2343
    if (pool)
        virStoragePoolObjUnlock(pool);
2344
    return ret;
C
Cole Robinson 已提交
2345 2346 2347 2348 2349
}

static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
                            const char *name) {
2350
    testConnPtr privconn = conn->privateData;
2351 2352
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
2353

2354
    testDriverLock(privconn);
2355
    pool = virStoragePoolObjFindByName(&privconn->pools, name);
2356
    testDriverUnlock(privconn);
2357 2358

    if (pool == NULL) {
C
Cole Robinson 已提交
2359
        testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL);
2360
        goto cleanup;
C
Cole Robinson 已提交
2361 2362
    }

2363 2364 2365
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
2366 2367
    if (pool)
        virStoragePoolObjUnlock(pool);
2368
    return ret;
C
Cole Robinson 已提交
2369 2370 2371 2372 2373 2374 2375 2376 2377
}

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

static int
testStorageNumPools(virConnectPtr conn) {
2378
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
2379 2380
    int numActive = 0, i;

2381
    testDriverLock(privconn);
C
Cole Robinson 已提交
2382 2383 2384
    for (i = 0 ; i < privconn->pools.count ; i++)
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numActive++;
2385
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
2386 2387 2388 2389 2390 2391 2392 2393

    return numActive;
}

static int
testStorageListPools(virConnectPtr conn,
                     char **const names,
                     int nnames) {
2394
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
2395 2396
    int n = 0, i;

2397
    testDriverLock(privconn);
C
Cole Robinson 已提交
2398
    memset(names, 0, sizeof(*names)*nnames);
2399 2400
    for (i = 0 ; i < privconn->pools.count && n < nnames ; i++) {
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
2401
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
2402 2403
            !(names[n++] = strdup(privconn->pools.objs[i]->def->name))) {
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
2404
            goto no_memory;
2405 2406 2407 2408
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
2409 2410 2411 2412

    return n;

no_memory:
2413
    virReportOOMError(conn);
C
Cole Robinson 已提交
2414 2415
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
2416
    testDriverUnlock(privconn);
2417
    return -1;
C
Cole Robinson 已提交
2418 2419 2420 2421
}

static int
testStorageNumDefinedPools(virConnectPtr conn) {
2422
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
2423 2424
    int numInactive = 0, i;

2425 2426 2427
    testDriverLock(privconn);
    for (i = 0 ; i < privconn->pools.count ; i++) {
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
2428 2429
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numInactive++;
2430 2431 2432
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
2433 2434 2435 2436 2437 2438 2439 2440

    return numInactive;
}

static int
testStorageListDefinedPools(virConnectPtr conn,
                            char **const names,
                            int nnames) {
2441
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
2442 2443
    int n = 0, i;

2444
    testDriverLock(privconn);
C
Cole Robinson 已提交
2445
    memset(names, 0, sizeof(*names)*nnames);
2446 2447
    for (i = 0 ; i < privconn->pools.count && n < nnames ; i++) {
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
2448
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
2449 2450
            !(names[n++] = strdup(privconn->pools.objs[i]->def->name))) {
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
2451
            goto no_memory;
2452 2453 2454 2455
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
2456 2457 2458 2459

    return n;

no_memory:
2460
    virReportOOMError(conn);
C
Cole Robinson 已提交
2461 2462
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
2463
    testDriverUnlock(privconn);
2464
    return -1;
C
Cole Robinson 已提交
2465 2466 2467 2468
}


static int
2469
testStoragePoolStart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2470
                     unsigned int flags ATTRIBUTE_UNUSED) {
2471 2472
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2473
    int ret = -1;
2474

2475
    testDriverLock(privconn);
2476 2477
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
2478
    testDriverUnlock(privconn);
2479 2480 2481

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2482
        goto cleanup;
2483 2484
    }

2485 2486 2487 2488 2489
    if (virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is already active"), pool->name);
        goto cleanup;
    }
C
Cole Robinson 已提交
2490 2491

    privpool->active = 1;
2492
    ret = 0;
C
Cole Robinson 已提交
2493

2494
cleanup:
2495 2496
    if (privpool)
        virStoragePoolObjUnlock(privpool);
2497
    return ret;
C
Cole Robinson 已提交
2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513
}

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) {
2514
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
2515
    virStoragePoolDefPtr def;
2516
    virStoragePoolObjPtr pool = NULL;
2517
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
2518

2519
    testDriverLock(privconn);
C
Cole Robinson 已提交
2520
    if (!(def = virStoragePoolDefParse(conn, xml, NULL)))
2521
        goto cleanup;
C
Cole Robinson 已提交
2522

2523 2524 2525 2526
    pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid);
    if (!pool)
        pool = virStoragePoolObjFindByName(&privconn->pools, def->name);
    if (pool) {
C
Cole Robinson 已提交
2527 2528
        testError(conn, VIR_ERR_INTERNAL_ERROR,
                  "%s", _("storage pool already exists"));
2529
        goto cleanup;
C
Cole Robinson 已提交
2530 2531
    }

2532
    if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, def)))
2533
        goto cleanup;
2534
    def = NULL;
C
Cole Robinson 已提交
2535

2536
    if (testStoragePoolObjSetDefaults(conn, pool) == -1) {
C
Cole Robinson 已提交
2537
        virStoragePoolObjRemove(&privconn->pools, pool);
2538 2539
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
2540 2541 2542
    }
    pool->active = 1;

2543 2544 2545 2546
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
    virStoragePoolDefFree(def);
2547 2548 2549
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
2550
    return ret;
C
Cole Robinson 已提交
2551 2552 2553 2554 2555 2556
}

static virStoragePoolPtr
testStoragePoolDefine(virConnectPtr conn,
                      const char *xml,
                      unsigned int flags ATTRIBUTE_UNUSED) {
2557
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
2558
    virStoragePoolDefPtr def;
2559
    virStoragePoolObjPtr pool = NULL;
2560
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
2561

2562
    testDriverLock(privconn);
C
Cole Robinson 已提交
2563
    if (!(def = virStoragePoolDefParse(conn, xml, NULL)))
2564
        goto cleanup;
C
Cole Robinson 已提交
2565 2566 2567 2568 2569

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

2570
    if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, def)))
2571 2572
        goto cleanup;
    def = NULL;
C
Cole Robinson 已提交
2573

2574
    if (testStoragePoolObjSetDefaults(conn, pool) == -1) {
C
Cole Robinson 已提交
2575
        virStoragePoolObjRemove(&privconn->pools, pool);
2576 2577
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
2578 2579
    }

2580 2581 2582 2583
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
    virStoragePoolDefFree(def);
2584 2585 2586
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
2587
    return ret;
C
Cole Robinson 已提交
2588 2589 2590
}

static int
2591 2592 2593
testStoragePoolUndefine(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2594
    int ret = -1;
2595

2596
    testDriverLock(privconn);
2597 2598 2599 2600 2601
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2602
        goto cleanup;
2603 2604
    }

2605 2606 2607 2608 2609
    if (virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is already active"), pool->name);
        goto cleanup;
    }
C
Cole Robinson 已提交
2610 2611

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

2614
cleanup:
2615 2616 2617
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
2618
    return ret;
C
Cole Robinson 已提交
2619 2620 2621
}

static int
2622
testStoragePoolBuild(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2623
                     unsigned int flags ATTRIBUTE_UNUSED) {
2624 2625
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2626
    int ret = -1;
2627

2628
    testDriverLock(privconn);
2629 2630
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
2631
    testDriverUnlock(privconn);
2632 2633 2634

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2635
        goto cleanup;
2636 2637
    }

2638 2639 2640 2641 2642
    if (virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is already active"), pool->name);
        goto cleanup;
    }
2643
    ret = 0;
C
Cole Robinson 已提交
2644

2645
cleanup:
2646 2647
    if (privpool)
        virStoragePoolObjUnlock(privpool);
2648
    return ret;
C
Cole Robinson 已提交
2649 2650 2651 2652
}


static int
2653 2654 2655
testStoragePoolDestroy(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2656
    int ret = -1;
2657

2658
    testDriverLock(privconn);
2659 2660 2661 2662 2663
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2664
        goto cleanup;
2665 2666 2667 2668 2669
    }

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

    privpool->active = 0;

2675
    if (privpool->configFile == NULL) {
C
Cole Robinson 已提交
2676
        virStoragePoolObjRemove(&privconn->pools, privpool);
2677 2678
        privpool = NULL;
    }
2679
    ret = 0;
C
Cole Robinson 已提交
2680

2681
cleanup:
2682 2683 2684
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
2685
    return ret;
C
Cole Robinson 已提交
2686 2687 2688 2689
}


static int
2690
testStoragePoolDelete(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2691
                      unsigned int flags ATTRIBUTE_UNUSED) {
2692 2693
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2694
    int ret = -1;
2695

2696
    testDriverLock(privconn);
2697 2698
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
2699
    testDriverUnlock(privconn);
2700 2701 2702

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2703 2704 2705 2706 2707 2708 2709
        goto cleanup;
    }

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

2712
    ret = 0;
C
Cole Robinson 已提交
2713

2714
cleanup:
2715 2716
    if (privpool)
        virStoragePoolObjUnlock(privpool);
2717
    return ret;
C
Cole Robinson 已提交
2718 2719 2720 2721
}


static int
2722
testStoragePoolRefresh(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2723
                       unsigned int flags ATTRIBUTE_UNUSED) {
2724 2725
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2726
    int ret = -1;
2727

2728
    testDriverLock(privconn);
2729 2730
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
2731
    testDriverUnlock(privconn);
2732 2733 2734

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2735
        goto cleanup;
2736 2737 2738 2739 2740
    }

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

2745
cleanup:
2746 2747
    if (privpool)
        virStoragePoolObjUnlock(privpool);
2748
    return ret;
C
Cole Robinson 已提交
2749 2750 2751 2752
}


static int
2753
testStoragePoolGetInfo(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2754
                       virStoragePoolInfoPtr info) {
2755 2756
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2757
    int ret = -1;
2758

2759
    testDriverLock(privconn);
2760 2761
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
2762
    testDriverUnlock(privconn);
2763 2764 2765

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2766
        goto cleanup;
2767
    }
C
Cole Robinson 已提交
2768 2769 2770 2771 2772 2773 2774 2775 2776

    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;
2777
    ret = 0;
C
Cole Robinson 已提交
2778

2779
cleanup:
2780 2781
    if (privpool)
        virStoragePoolObjUnlock(privpool);
2782
    return ret;
C
Cole Robinson 已提交
2783 2784 2785
}

static char *
2786
testStoragePoolDumpXML(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2787
                       unsigned int flags ATTRIBUTE_UNUSED) {
2788 2789
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2790
    char *ret = NULL;
2791

2792
    testDriverLock(privconn);
2793 2794
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
2795
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
2796

2797 2798
    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2799
        goto cleanup;
2800 2801
    }

2802 2803 2804
    ret = virStoragePoolDefFormat(pool->conn, privpool->def);

cleanup:
2805 2806
    if (privpool)
        virStoragePoolObjUnlock(privpool);
2807
    return ret;
C
Cole Robinson 已提交
2808 2809 2810
}

static int
2811
testStoragePoolGetAutostart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2812
                            int *autostart) {
2813 2814
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2815
    int ret = -1;
2816

2817
    testDriverLock(privconn);
2818 2819
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
2820
    testDriverUnlock(privconn);
2821 2822 2823

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2824
        goto cleanup;
2825
    }
C
Cole Robinson 已提交
2826 2827 2828 2829 2830 2831

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

2834
cleanup:
2835 2836
    if (privpool)
        virStoragePoolObjUnlock(privpool);
2837
    return ret;
C
Cole Robinson 已提交
2838 2839 2840
}

static int
2841
testStoragePoolSetAutostart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2842
                            int autostart) {
2843 2844
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2845
    int ret = -1;
2846

2847
    testDriverLock(privconn);
2848 2849
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
2850
    testDriverUnlock(privconn);
2851 2852 2853

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2854
        goto cleanup;
2855
    }
C
Cole Robinson 已提交
2856 2857

    if (!privpool->configFile) {
2858
        testError(pool->conn, VIR_ERR_INVALID_ARG,
C
Cole Robinson 已提交
2859
                  "%s", _("pool has no config file"));
2860
        goto cleanup;
C
Cole Robinson 已提交
2861 2862 2863 2864
    }

    autostart = (autostart != 0);
    privpool->autostart = autostart;
2865 2866 2867
    ret = 0;

cleanup:
2868 2869
    if (privpool)
        virStoragePoolObjUnlock(privpool);
2870
    return ret;
C
Cole Robinson 已提交
2871 2872 2873 2874
}


static int
2875 2876 2877
testStoragePoolNumVolumes(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
2878
    int ret = -1;
2879

2880
    testDriverLock(privconn);
2881 2882
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
2883
    testDriverUnlock(privconn);
2884 2885 2886

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2887
        goto cleanup;
2888 2889 2890 2891 2892
    }

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

2896 2897 2898
    ret = privpool->volumes.count;

cleanup:
2899 2900
    if (privpool)
        virStoragePoolObjUnlock(privpool);
2901
    return ret;
C
Cole Robinson 已提交
2902 2903 2904
}

static int
2905
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2906 2907
                           char **const names,
                           int maxnames) {
2908 2909
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
C
Cole Robinson 已提交
2910 2911
    int i = 0, n = 0;

2912
    memset(names, 0, maxnames * sizeof(*names));
2913 2914

    testDriverLock(privconn);
2915 2916
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
2917
    testDriverUnlock(privconn);
2918 2919 2920

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2921
        goto cleanup;
2922 2923 2924 2925 2926 2927
    }


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

C
Cole Robinson 已提交
2931 2932
    for (i = 0 ; i < privpool->volumes.count && n < maxnames ; i++) {
        if ((names[n++] = strdup(privpool->volumes.objs[i]->name)) == NULL) {
2933
            virReportOOMError(pool->conn);
C
Cole Robinson 已提交
2934 2935 2936 2937
            goto cleanup;
        }
    }

2938
    virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
2939 2940 2941 2942 2943 2944
    return n;

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

2945
    memset(names, 0, maxnames * sizeof(*names));
2946 2947
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
2948 2949 2950 2951 2952
    return -1;
}


static virStorageVolPtr
2953
testStorageVolumeLookupByName(virStoragePoolPtr pool,
C
Cole Robinson 已提交
2954
                              const char *name ATTRIBUTE_UNUSED) {
2955 2956 2957
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
2958
    virStorageVolPtr ret = NULL;
2959

2960
    testDriverLock(privconn);
2961 2962
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
2963
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
2964

2965 2966
    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2967
        goto cleanup;
2968 2969 2970 2971 2972 2973
    }


    if (!virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is not active"), pool->name);
2974
        goto cleanup;
2975 2976 2977 2978 2979 2980
    }

    privvol = virStorageVolDefFindByName(privpool, name);

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

2985 2986 2987 2988
    ret = virGetStorageVol(pool->conn, privpool->def->name,
                           privvol->name, privvol->key);

cleanup:
2989 2990
    if (privpool)
        virStoragePoolObjUnlock(privpool);
2991
    return ret;
C
Cole Robinson 已提交
2992 2993 2994 2995 2996 2997
}


static virStorageVolPtr
testStorageVolumeLookupByKey(virConnectPtr conn,
                             const char *key) {
2998
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
2999
    unsigned int i;
3000
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
3001

3002
    testDriverLock(privconn);
C
Cole Robinson 已提交
3003
    for (i = 0 ; i < privconn->pools.count ; i++) {
3004
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3005
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
3006
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
3007 3008
                virStorageVolDefFindByKey(privconn->pools.objs[i], key);

3009 3010 3011 3012 3013
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
                                       privvol->key);
3014
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
3015 3016
                break;
            }
C
Cole Robinson 已提交
3017
        }
3018
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3019
    }
3020
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3021

3022 3023 3024 3025 3026
    if (!ret)
        testError(conn, VIR_ERR_INVALID_STORAGE_VOL,
                  _("no storage vol with matching key '%s'"), key);

    return ret;
C
Cole Robinson 已提交
3027 3028 3029 3030 3031
}

static virStorageVolPtr
testStorageVolumeLookupByPath(virConnectPtr conn,
                              const char *path) {
3032
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
3033
    unsigned int i;
3034
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
3035

3036
    testDriverLock(privconn);
C
Cole Robinson 已提交
3037
    for (i = 0 ; i < privconn->pools.count ; i++) {
3038
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3039
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
3040
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
3041 3042
                virStorageVolDefFindByPath(privconn->pools.objs[i], path);

3043 3044 3045 3046 3047
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
                                       privvol->key);
3048
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
3049 3050
                break;
            }
C
Cole Robinson 已提交
3051
        }
3052
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3053
    }
3054
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3055

3056 3057 3058 3059 3060
    if (!ret)
        testError(conn, VIR_ERR_INVALID_STORAGE_VOL,
                  _("no storage vol with matching path '%s'"), path);

    return ret;
C
Cole Robinson 已提交
3061 3062 3063
}

static virStorageVolPtr
3064
testStorageVolumeCreateXML(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3065 3066
                           const char *xmldesc,
                           unsigned int flags ATTRIBUTE_UNUSED) {
3067 3068
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3069 3070
    virStorageVolDefPtr privvol = NULL;
    virStorageVolPtr ret = NULL;
3071

3072
    testDriverLock(privconn);
3073 3074
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3075
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3076

3077 3078
    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3079
        goto cleanup;
3080 3081 3082 3083 3084
    }

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

3088 3089
    privvol = virStorageVolDefParse(pool->conn, privpool->def, xmldesc, NULL);
    if (privvol == NULL)
3090
        goto cleanup;
3091 3092

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
3093
        testError(pool->conn, VIR_ERR_INVALID_STORAGE_VOL,
C
Cole Robinson 已提交
3094
                  "%s", _("storage vol already exists"));
3095
        goto cleanup;
C
Cole Robinson 已提交
3096 3097 3098
    }

    /* Make sure enough space */
3099
    if ((privpool->def->allocation + privvol->allocation) >
C
Cole Robinson 已提交
3100
         privpool->def->capacity) {
3101
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
C
Cole Robinson 已提交
3102
                  _("Not enough free space in pool for volume '%s'"),
3103
                  privvol->name);
3104
        goto cleanup;
C
Cole Robinson 已提交
3105 3106 3107 3108
    }

    if (VIR_REALLOC_N(privpool->volumes.objs,
                      privpool->volumes.count+1) < 0) {
3109
        virReportOOMError(pool->conn);
3110
        goto cleanup;
C
Cole Robinson 已提交
3111 3112
    }

3113 3114 3115
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
                    privvol->name) == -1) {
3116
        virReportOOMError(pool->conn);
3117
        goto cleanup;
C
Cole Robinson 已提交
3118 3119
    }

3120 3121
    privvol->key = strdup(privvol->target.path);
    if (privvol->key == NULL) {
3122
        virReportOOMError(pool->conn);
3123
        goto cleanup;
C
Cole Robinson 已提交
3124 3125
    }

3126
    privpool->def->allocation += privvol->allocation;
C
Cole Robinson 已提交
3127 3128 3129
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

3130
    privpool->volumes.objs[privpool->volumes.count++] = privvol;
C
Cole Robinson 已提交
3131

3132 3133
    ret = virGetStorageVol(pool->conn, privpool->def->name,
                           privvol->name, privvol->key);
3134
    privvol = NULL;
3135 3136 3137

cleanup:
    virStorageVolDefFree(privvol);
3138 3139
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3140
    return ret;
C
Cole Robinson 已提交
3141 3142
}

3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203
static virStorageVolPtr
testStorageVolumeCreateXMLFrom(virStoragePoolPtr pool,
                               const char *xmldesc,
                               virStorageVolPtr clonevol,
                               unsigned int flags ATTRIBUTE_UNUSED) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol = NULL, origvol = NULL;
    virStorageVolPtr ret = NULL;

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

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

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

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

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
        testError(pool->conn, VIR_ERR_INVALID_STORAGE_VOL,
                  "%s", _("storage vol already exists"));
        goto cleanup;
    }

    origvol = virStorageVolDefFindByName(privpool, clonevol->name);
    if (!origvol) {
        testError(pool->conn, VIR_ERR_INVALID_STORAGE_VOL,
                  _("no storage vol with matching name '%s'"),
                  clonevol->name);
        goto cleanup;
    }

    /* Make sure enough space */
    if ((privpool->def->allocation + privvol->allocation) >
         privpool->def->capacity) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Not enough free space in pool for volume '%s'"),
                  privvol->name);
        goto cleanup;
    }
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    if (VIR_REALLOC_N(privpool->volumes.objs,
                      privpool->volumes.count+1) < 0) {
        virReportOOMError(pool->conn);
        goto cleanup;
    }

3204 3205 3206
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
                    privvol->name) == -1) {
3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233
        virReportOOMError(pool->conn);
        goto cleanup;
    }

    privvol->key = strdup(privvol->target.path);
    if (privvol->key == NULL) {
        virReportOOMError(pool->conn);
        goto cleanup;
    }

    privpool->def->allocation += privvol->allocation;
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    privpool->volumes.objs[privpool->volumes.count++] = privvol;

    ret = virGetStorageVol(pool->conn, privpool->def->name,
                           privvol->name, privvol->key);
    privvol = NULL;

cleanup:
    virStorageVolDefFree(privvol);
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    return ret;
}

C
Cole Robinson 已提交
3234
static int
3235
testStorageVolumeDelete(virStorageVolPtr vol,
C
Cole Robinson 已提交
3236
                        unsigned int flags ATTRIBUTE_UNUSED) {
3237 3238 3239
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
C
Cole Robinson 已提交
3240
    int i;
3241
    int ret = -1;
C
Cole Robinson 已提交
3242

3243
    testDriverLock(privconn);
3244 3245
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
3246
    testDriverUnlock(privconn);
3247 3248 3249

    if (privpool == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3250
        goto cleanup;
3251 3252 3253 3254 3255 3256 3257 3258 3259
    }


    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);
3260
        goto cleanup;
3261 3262 3263 3264 3265
    }

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


C
Cole Robinson 已提交
3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292
    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;
        }
    }
3293
    ret = 0;
C
Cole Robinson 已提交
3294

3295
cleanup:
3296 3297
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3298
    return ret;
C
Cole Robinson 已提交
3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314
}


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
3315
testStorageVolumeGetInfo(virStorageVolPtr vol,
C
Cole Robinson 已提交
3316
                         virStorageVolInfoPtr info) {
3317 3318 3319
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
3320
    int ret = -1;
3321

3322
    testDriverLock(privconn);
3323 3324
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
3325
    testDriverUnlock(privconn);
3326 3327 3328

    if (privpool == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3329
        goto cleanup;
3330 3331 3332 3333 3334 3335 3336 3337
    }

    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);
3338
        goto cleanup;
3339 3340 3341 3342 3343
    }

    if (!virStoragePoolObjIsActive(privpool)) {
        testError(vol->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is not active"), vol->pool);
3344
        goto cleanup;
3345
    }
C
Cole Robinson 已提交
3346 3347 3348 3349 3350

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

3353
cleanup:
3354 3355
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3356
    return ret;
C
Cole Robinson 已提交
3357 3358 3359
}

static char *
3360
testStorageVolumeGetXMLDesc(virStorageVolPtr vol,
C
Cole Robinson 已提交
3361
                            unsigned int flags ATTRIBUTE_UNUSED) {
3362 3363 3364
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
3365
    char *ret = NULL;
3366

3367
    testDriverLock(privconn);
3368 3369
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
3370
    testDriverUnlock(privconn);
3371 3372 3373

    if (privpool == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3374
        goto cleanup;
3375 3376 3377 3378 3379 3380 3381 3382
    }

    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);
3383
        goto cleanup;
3384
    }
C
Cole Robinson 已提交
3385

3386 3387 3388
    if (!virStoragePoolObjIsActive(privpool)) {
        testError(vol->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is not active"), vol->pool);
3389
        goto cleanup;
3390 3391
    }

3392 3393 3394
    ret = virStorageVolDefFormat(vol->conn, privpool->def, privvol);

cleanup:
3395 3396
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3397
    return ret;
C
Cole Robinson 已提交
3398 3399 3400
}

static char *
3401 3402 3403 3404
testStorageVolumeGetPath(virStorageVolPtr vol) {
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
3405
    char *ret = NULL;
3406

3407
    testDriverLock(privconn);
3408 3409
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
3410
    testDriverUnlock(privconn);
3411 3412 3413

    if (privpool == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3414
        goto cleanup;
3415 3416 3417 3418 3419 3420 3421 3422
    }

    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);
3423
        goto cleanup;
3424 3425 3426 3427 3428
    }

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

C
Cole Robinson 已提交
3432
    ret = strdup(privvol->target.path);
3433
    if (ret == NULL)
3434
        virReportOOMError(vol->conn);
3435 3436

cleanup:
3437 3438
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
3439 3440 3441
    return ret;
}

3442

3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458
static virDrvOpenStatus testDevMonOpen(virConnectPtr conn,
                                       virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                       int flags ATTRIBUTE_UNUSED) {
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

    conn->devMonPrivateData = conn->privateData;
    return VIR_DRV_OPEN_SUCCESS;
}

static int testDevMonClose(virConnectPtr conn) {
    conn->devMonPrivateData = NULL;
    return 0;
}


3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555
static int
testDomainEventRegister (virConnectPtr conn,
                         virConnectDomainEventCallback callback,
                         void *opaque,
                         virFreeCallback freecb)
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
    ret = virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks,
                                        callback, opaque, freecb);
    testDriverUnlock(driver);

    return ret;
}

static int
testDomainEventDeregister (virConnectPtr conn,
                           virConnectDomainEventCallback callback)
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
    if (driver->domainEventDispatching)
        ret = virDomainEventCallbackListMarkDelete(conn, driver->domainEventCallbacks,
                                                   callback);
    else
        ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks,
                                               callback);
    testDriverUnlock(driver);

    return ret;
}

static void testDomainEventDispatchFunc(virConnectPtr conn,
                                        virDomainEventPtr event,
                                        virConnectDomainEventCallback cb,
                                        void *cbopaque,
                                        void *opaque)
{
    testConnPtr driver = opaque;

    /* Drop the lock whle dispatching, for sake of re-entrancy */
    testDriverUnlock(driver);
    virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL);
    testDriverLock(driver);
}

static void testDomainEventFlush(int timer ATTRIBUTE_UNUSED, void *opaque)
{
    testConnPtr driver = opaque;
    virDomainEventQueue tempQueue;

    testDriverLock(driver);

    driver->domainEventDispatching = 1;

    /* Copy the queue, so we're reentrant safe */
    tempQueue.count = driver->domainEventQueue->count;
    tempQueue.events = driver->domainEventQueue->events;
    driver->domainEventQueue->count = 0;
    driver->domainEventQueue->events = NULL;

    virEventUpdateTimeout(driver->domainEventTimer, -1);
    virDomainEventQueueDispatch(&tempQueue,
                                driver->domainEventCallbacks,
                                testDomainEventDispatchFunc,
                                driver);

    /* Purge any deleted callbacks */
    virDomainEventCallbackListPurgeMarked(driver->domainEventCallbacks);

    driver->domainEventDispatching = 0;
    testDriverUnlock(driver);
}


/* driver must be locked before calling */
static void testDomainEventQueue(testConnPtr driver,
                                 virDomainEventPtr event)
{
    if (driver->domainEventTimer < 0) {
        virDomainEventFree(event);
        return;
    }

    if (virDomainEventQueuePush(driver->domainEventQueue,
                                event) < 0)
        virDomainEventFree(event);

    if (driver->domainEventQueue->count == 1)
        virEventUpdateTimeout(driver->domainEventTimer, 0);
}


3556 3557 3558 3559 3560
static virDriver testDriver = {
    VIR_DRV_TEST,
    "Test",
    testOpen, /* open */
    testClose, /* close */
3561
    NULL, /* supports_feature */
3562 3563
    NULL, /* type */
    testGetVersion, /* version */
3564
    testGetHostname, /* getHostname */
3565 3566 3567 3568 3569
    testGetMaxVCPUs, /* getMaxVcpus */
    testNodeGetInfo, /* nodeGetInfo */
    testGetCapabilities, /* getCapabilities */
    testListDomains, /* listDomains */
    testNumOfDomains, /* numOfDomains */
3570
    testDomainCreateXML, /* domainCreateXML */
3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590
    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 */
3591 3592
    NULL, /* domainGetSecurityLabel */
    NULL, /* nodeGetSecurityModel */
3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605
    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 */
3606 3607 3608
    NULL, /* domainMigratePrepare */
    NULL, /* domainMigratePerform */
    NULL, /* domainMigrateFinish */
3609 3610
    NULL, /* domainBlockStats */
    NULL, /* domainInterfaceStats */
R
Richard W.M. Jones 已提交
3611
    NULL, /* domainBlockPeek */
R
Richard W.M. Jones 已提交
3612
    NULL, /* domainMemoryPeek */
3613
    testNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
3614
    NULL, /* getFreeMemory */
3615 3616
    testDomainEventRegister, /* domainEventRegister */
    testDomainEventDeregister, /* domainEventDeregister */
D
Daniel Veillard 已提交
3617 3618
    NULL, /* domainMigratePrepare2 */
    NULL, /* domainMigrateFinish2 */
3619
    NULL, /* nodeDeviceDettach */
3620 3621
    NULL, /* nodeDeviceReAttach */
    NULL, /* nodeDeviceReset */
3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644
};

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

3645 3646 3647 3648
static virStorageDriver testStorageDriver = {
    .name = "Test",
    .open = testStorageOpen,
    .close = testStorageClose,
C
Cole Robinson 已提交
3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676

    .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,
3677
    .volCreateXMLFrom = testStorageVolumeCreateXMLFrom,
C
Cole Robinson 已提交
3678 3679 3680 3681
    .volDelete = testStorageVolumeDelete,
    .volGetInfo = testStorageVolumeGetInfo,
    .volGetXMLDesc = testStorageVolumeGetXMLDesc,
    .volGetPath = testStorageVolumeGetPath,
3682 3683
};

3684 3685 3686 3687 3688 3689 3690 3691
static virDeviceMonitor testDevMonitor = {
    .name = "Test",
    .open = testDevMonOpen,
    .close = testDevMonClose,
};



3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
    if (virRegisterDriver(&testDriver) < 0)
        return -1;
    if (virRegisterNetworkDriver(&testNetworkDriver) < 0)
        return -1;
3704 3705
    if (virRegisterStorageDriver(&testStorageDriver) < 0)
        return -1;
3706 3707 3708
    if (virRegisterDeviceMonitor(&testDevMonitor) < 0)
        return -1;

3709 3710
    return 0;
}