test_driver.c 136.8 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_driver.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"
L
Laine Stump 已提交
44
#include "interface_conf.h"
45
#include "domain_conf.h"
46 47
#include "domain_event.h"
#include "event.h"
C
Cole Robinson 已提交
48
#include "storage_conf.h"
49
#include "node_device_conf.h"
50
#include "xml.h"
51
#include "threads.h"
52
#include "logging.h"
53

54 55
#define VIR_FROM_THIS VIR_FROM_TEST

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

68
struct _testConn {
69
    virMutex lock;
70

71 72
    char path[PATH_MAX];
    int nextDomID;
73
    virCapsPtr caps;
74
    virNodeInfo nodeInfo;
75
    virDomainObjList domains;
76
    virNetworkObjList networks;
L
Laine Stump 已提交
77
    virInterfaceObjList ifaces;
C
Cole Robinson 已提交
78
    virStoragePoolObjList pools;
79
    virNodeDeviceObjList devs;
80 81
    int numCells;
    testCell cells[MAX_CELLS];
82 83 84 85 86 87 88


    /* An array of callbacks */
    virDomainEventCallbackListPtr domainEventCallbacks;
    virDomainEventQueuePtr domainEventQueue;
    int domainEventTimer;
    int domainEventDispatching;
89 90 91
};
typedef struct _testConn testConn;
typedef struct _testConn *testConnPtr;
92

93
#define TEST_MODEL "i686"
94
#define TEST_MODEL_WORDSIZE 32
95
#define TEST_EMULATOR "/usr/bin/test-hv"
96

97
static const virNodeInfo defaultNodeInfo = {
98
    TEST_MODEL,
99 100 101 102 103 104 105
    1024*1024*3, /* 3 GB */
    16,
    1400,
    2,
    2,
    2,
    2,
106 107
};

108

109
#define testError(conn, code, fmt...)                               \
110
        virReportErrorHelper(conn, VIR_FROM_TEST, code, __FILE__, \
111
                               __FUNCTION__, __LINE__, fmt)
112

113 114 115 116 117 118
static int testClose(virConnectPtr conn);
static void testDomainEventFlush(int timer, void *opaque);
static void testDomainEventQueue(testConnPtr driver,
                                 virDomainEventPtr event);


119 120
static void testDriverLock(testConnPtr driver)
{
121
    virMutexLock(&driver->lock);
122 123 124 125
}

static void testDriverUnlock(testConnPtr driver)
{
126
    virMutexUnlock(&driver->lock);
127 128
}

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

137 138
    if ((caps = virCapabilitiesNew(TEST_MODEL, 0, 0)) == NULL)
        goto no_memory;
139

140 141 142 143
    if (virCapabilitiesAddHostFeature(caps, "pae") < 0)
        goto no_memory;
    if (virCapabilitiesAddHostFeature(caps ,"nonpae") < 0)
        goto no_memory;
144

145 146 147 148
    for (i = 0; i < privconn->numCells; i++) {
        if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].numCpus,
                                           privconn->cells[i].cpus) < 0)
            goto no_memory;
149 150
    }

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

162 163 164 165 166 167 168
        if (virCapabilitiesAddGuestDomain(guest,
                                          "test",
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
            goto no_memory;
169

170 171 172 173
        if (virCapabilitiesAddGuestFeature(guest, "pae", 1, 1) == NULL)
            goto no_memory;
        if (virCapabilitiesAddGuestFeature(guest ,"nonpae", 1, 1) == NULL)
            goto no_memory;
174 175
    }

176
    return caps;
177

178
no_memory:
179
    virReportOOMError(conn);
180 181
    virCapabilitiesFree(caps);
    return NULL;
182 183
}

184

185 186 187 188 189 190 191 192 193 194
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>";
195 196


197 198 199 200 201 202 203 204 205 206 207
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>";
208

L
Laine Stump 已提交
209 210 211 212 213 214 215 216 217 218 219
static const char *defaultInterfaceXML =
"<interface type=\"ethernet\" name=\"eth1\">"
"  <start mode=\"onboot\"/>"
"  <mac address=\"aa:bb:cc:dd:ee:ff\"/>"
"  <mtu size=\"1492\"/>"
"  <protocol family=\"ipv4\">"
"    <ip address=\"192.168.0.5\" prefix=\"24\"/>"
"    <route gateway=\"192.168.0.1\"/>"
"  </protocol>"
"</interface>";

C
Cole Robinson 已提交
220 221 222 223 224 225 226 227
static const char *defaultPoolXML =
"<pool type='dir'>"
"  <name>default-pool</name>"
"  <target>"
"    <path>/default-pool</path>"
"  </target>"
"</pool>";

228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
static const char *defaultPoolSourcesLogicalXML =
"<sources>\n"
"  <source>\n"
"    <device path='/dev/sda20'/>\n"
"    <name>testvg1</name>\n"
"    <format type='lvm2'/>\n"
"  </source>\n"
"  <source>\n"
"    <device path='/dev/sda21'/>\n"
"    <name>testvg2</name>\n"
"    <format type='lvm2'/>\n"
"  </source>\n"
"</sources>\n";

static const char *defaultPoolSourcesNetFSXML =
"<sources>\n"
"  <source>\n"
"    <host name='%s'/>\n"
"    <dir path='/testshare'/>\n"
"    <format type='nfs'/>\n"
"  </source>\n"
"</sources>\n";

251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
static const char *defaultNodeXML =
"<device>"
"  <name>computer</name>"
"  <capability type='system'>"
"    <hardware>"
"      <vendor>Libvirt</vendor>"
"      <version>Test driver</version>"
"      <serial>123456</serial>"
"      <uuid>11111111-2222-3333-4444-555555555555</uuid>"
"    </hardware>"
"    <firmware>"
"      <vendor>Libvirt</vendor>"
"      <version>Test Driver</version>"
"      <release_date>01/22/2007</release_date>"
"    </firmware>"
"  </capability>"
"</device>";

269
static const unsigned long long defaultPoolCap = (100 * 1024 * 1024 * 1024ull);
C
Cole Robinson 已提交
270 271
static const unsigned long long defaultPoolAlloc = 0;

272
static int testStoragePoolObjSetDefaults(virConnectPtr conn, virStoragePoolObjPtr pool);
273

274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
static char *
testDomainGenerateIfname(virConnectPtr conn,
                         virDomainDefPtr domdef) {
    int maxif = 1024;
    int ifctr, i;

    for (ifctr = 0; ifctr < maxif; ++ifctr) {
        char *ifname;
        int found = 0;

        if (virAsprintf(&ifname, "testnet%d", ifctr) < 0) {
            virReportOOMError(conn);
            return NULL;
        }

        /* Generate network interface names */
        for (i = 0 ; i < domdef->nnets ; i++) {
            if (domdef->nets[i]->ifname &&
                STREQ (domdef->nets[i]->ifname, ifname)) {
                found = 1;
                break;
            }
        }

        if (!found)
            return ifname;
    }

    testError(conn, VIR_ERR_INTERNAL_ERROR,
              _("Exceeded max iface limit %d"), maxif);
    return NULL;
}

307 308 309
static int
testDomainGenerateIfnames(virConnectPtr conn,
                          virDomainDefPtr domdef)
310 311 312 313 314 315 316 317 318 319
{
    int i = 0;

    for (i = 0; i < domdef->nnets; i++) {
        char *ifname;
        if (domdef->nets[i]->ifname)
            continue;

        ifname = testDomainGenerateIfname(conn, domdef);
        if (!ifname)
320
            return -1;
321 322 323 324

        domdef->nets[i]->ifname = ifname;
    }

325
    return 0;
326 327
}

328

329
static int testOpenDefault(virConnectPtr conn) {
330 331
    int u;
    struct timeval tv;
332
    testConnPtr privconn;
333 334 335 336
    virDomainDefPtr domdef = NULL;
    virDomainObjPtr domobj = NULL;
    virNetworkDefPtr netdef = NULL;
    virNetworkObjPtr netobj = NULL;
L
Laine Stump 已提交
337 338
    virInterfaceDefPtr interfacedef = NULL;
    virInterfaceObjPtr interfaceobj = NULL;
C
Cole Robinson 已提交
339 340
    virStoragePoolDefPtr pooldef = NULL;
    virStoragePoolObjPtr poolobj = NULL;
341 342
    virNodeDeviceDefPtr nodedef = NULL;
    virNodeDeviceObjPtr nodeobj = NULL;
343

344
    if (VIR_ALLOC(privconn) < 0) {
345
        virReportOOMError(conn);
346 347
        return VIR_DRV_OPEN_ERROR;
    }
348 349 350 351 352 353 354
    if (virMutexInit(&privconn->lock) < 0) {
        testError(conn, VIR_ERR_INTERNAL_ERROR,
                  "%s", _("cannot initialize mutex"));
        VIR_FREE(privconn);
        return VIR_DRV_OPEN_ERROR;
    }

355
    testDriverLock(privconn);
356
    conn->privateData = privconn;
357 358

    if (gettimeofday(&tv, NULL) < 0) {
359 360
        virReportSystemError(conn, errno,
                             "%s", _("getting time of day"));
361
        goto error;
362 363
    }

364 365 366
    if (virDomainObjListInit(&privconn->domains) < 0)
        goto error;

367
    memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));
368

369 370 371 372 373 374 375 376 377 378
    // 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;
    }

379 380 381 382 383
    if (!(privconn->caps = testBuildCapabilities(conn)))
        goto error;

    privconn->nextDomID = 1;

384 385 386
    if (!(domdef = virDomainDefParseString(conn, privconn->caps,
                                           defaultDomainXML,
                                           VIR_DOMAIN_XML_INACTIVE)))
387
        goto error;
388
    if (testDomainGenerateIfnames(conn, domdef) < 0)
389
        goto error;
390 391
    if (!(domobj = virDomainAssignDef(conn, privconn->caps,
                                      &privconn->domains, domdef)))
392 393
        goto error;
    domdef = NULL;
394
    domobj->def->id = privconn->nextDomID++;
395 396
    domobj->state = VIR_DOMAIN_RUNNING;
    domobj->persistent = 1;
397
    virDomainObjUnlock(domobj);
398 399 400 401 402 403 404 405 406

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

L
Laine Stump 已提交
409 410 411 412 413 414 415 416 417
    if (!(interfacedef = virInterfaceDefParseString(conn, defaultInterfaceXML)))
        goto error;
    if (!(interfaceobj = virInterfaceAssignDef(conn, &privconn->ifaces, interfacedef))) {
        virInterfaceDefFree(interfacedef);
        goto error;
    }
    interfaceobj->active = 1;
    virInterfaceObjUnlock(interfaceobj);

418
    if (!(pooldef = virStoragePoolDefParseString(conn, defaultPoolXML)))
C
Cole Robinson 已提交
419 420 421 422 423 424 425
        goto error;

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

427
    if (testStoragePoolObjSetDefaults(conn, poolobj) == -1) {
428
        virStoragePoolObjUnlock(poolobj);
C
Cole Robinson 已提交
429
        goto error;
430
    }
C
Cole Robinson 已提交
431
    poolobj->active = 1;
432
    virStoragePoolObjUnlock(poolobj);
C
Cole Robinson 已提交
433

434 435 436 437 438 439 440 441 442 443
    /* Init default node device */
    if (!(nodedef = virNodeDeviceDefParseString(conn, defaultNodeXML, 0)))
        goto error;
    if (!(nodeobj = virNodeDeviceAssignDef(conn, &privconn->devs,
                                           nodedef))) {
        virNodeDeviceDefFree(nodedef);
        goto error;
    }
    virNodeDeviceObjUnlock(nodeobj);

444
    testDriverUnlock(privconn);
445

446 447 448
    return VIR_DRV_OPEN_SUCCESS;

error:
449
    virDomainObjListDeinit(&privconn->domains);
450
    virNetworkObjListFree(&privconn->networks);
L
Laine Stump 已提交
451
    virInterfaceObjListFree(&privconn->ifaces);
C
Cole Robinson 已提交
452
    virStoragePoolObjListFree(&privconn->pools);
453
    virNodeDeviceObjListFree(&privconn->devs);
454
    virCapabilitiesFree(privconn->caps);
455
    testDriverUnlock(privconn);
456
    conn->privateData = NULL;
457
    VIR_FREE(privconn);
458
    virDomainDefFree(domdef);
459
    return VIR_DRV_OPEN_ERROR;
460 461 462 463
}


static char *testBuildFilename(const char *relativeTo,
464 465 466 467 468 469 470 471
                               const char *filename) {
    char *offset;
    int baseLen;
    if (!filename || filename[0] == '\0')
        return (NULL);
    if (filename[0] == '/')
        return strdup(filename);

472
    offset = strrchr(relativeTo, '/');
473
    if ((baseLen = (offset-relativeTo+1))) {
474
        char *absFile;
C
Chris Lalancette 已提交
475 476
        int totalLen = baseLen + strlen(filename) + 1;
        if (VIR_ALLOC_N(absFile, totalLen) < 0)
477
            return NULL;
C
Chris Lalancette 已提交
478 479 480 481
        if (virStrncpy(absFile, relativeTo, baseLen, totalLen) == NULL) {
            VIR_FREE(absFile);
            return NULL;
        }
482 483 484 485 486
        strcat(absFile, filename);
        return absFile;
    } else {
        return strdup(filename);
    }
487 488
}

489 490 491 492 493 494 495 496 497
static int testOpenVolumesForPool(virConnectPtr conn,
                                  xmlDocPtr xml,
                                  xmlXPathContextPtr ctxt,
                                  const char *file,
                                  virStoragePoolObjPtr pool,
                                  int poolidx) {
    char *vol_xpath;
    int i, ret, func_ret = -1;
    xmlNodePtr *vols = NULL;
498
    virStorageVolDefPtr def = NULL;
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569

    /* Find storage volumes */
    if (virAsprintf(&vol_xpath, "/node/pool[%d]/volume", poolidx) < 0) {
        virReportOOMError(NULL);
        goto error;
    }

    ret = virXPathNodeSet(conn, vol_xpath, ctxt, &vols);
    VIR_FREE(vol_xpath);
    if (ret < 0) {
        testError(NULL, VIR_ERR_XML_ERROR,
                  _("node vol list for pool '%s'"), pool->def->name);
        goto error;
    }

    for (i = 0 ; i < ret ; i++) {
        char *relFile = virXMLPropString(vols[i], "file");
        if (relFile != NULL) {
            char *absFile = testBuildFilename(file, relFile);
            VIR_FREE(relFile);
            if (!absFile) {
                testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s",
                          _("resolving volume filename"));
                goto error;
            }

            def = virStorageVolDefParseFile(conn, pool->def, absFile);
            VIR_FREE(absFile);
            if (!def)
                goto error;
        } else {
            if ((def = virStorageVolDefParseNode(conn, pool->def, xml,
                                                 vols[i])) == NULL) {
                goto error;
            }
        }

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

        if (virAsprintf(&def->target.path, "%s/%s",
                        pool->def->target.path,
                        def->name) == -1) {
            virReportOOMError(conn);
            goto error;
        }

        def->key = strdup(def->target.path);
        if (def->key == NULL) {
            virReportOOMError(conn);
            goto error;
        }

        pool->def->allocation += def->allocation;
        pool->def->available = (pool->def->capacity -
                                pool->def->allocation);

        pool->volumes.objs[pool->volumes.count++] = def;
        def = NULL;
    }

    func_ret = 0;
error:
    virStorageVolDefFree(def);
    VIR_FREE(vols);
    return func_ret;
}

570
static int testOpenFromFile(virConnectPtr conn,
571
                            const char *file) {
572
    int fd = -1, i, ret;
573 574
    long l;
    char *str;
575
    xmlDocPtr xml = NULL;
576
    xmlNodePtr root = NULL;
577 578
    xmlNodePtr *domains = NULL, *networks = NULL, *ifaces = NULL,
               *pools = NULL, *devs = NULL;
579 580
    xmlXPathContextPtr ctxt = NULL;
    virNodeInfoPtr nodeInfo;
581
    virNetworkObjPtr net;
L
Laine Stump 已提交
582
    virInterfaceObjPtr iface;
583
    virDomainObjPtr dom;
584 585
    testConnPtr privconn;
    if (VIR_ALLOC(privconn) < 0) {
586
        virReportOOMError(conn);
587 588
        return VIR_DRV_OPEN_ERROR;
    }
589 590 591 592 593 594 595
    if (virMutexInit(&privconn->lock) < 0) {
        testError(conn, VIR_ERR_INTERNAL_ERROR,
                  "%s", _("cannot initialize mutex"));
        VIR_FREE(privconn);
        return VIR_DRV_OPEN_ERROR;
    }

596
    testDriverLock(privconn);
597
    conn->privateData = privconn;
598

599 600 601
    if (virDomainObjListInit(&privconn->domains) < 0)
        goto error;

602 603
    if (!(privconn->caps = testBuildCapabilities(conn)))
        goto error;
604 605

    if ((fd = open(file, O_RDONLY)) < 0) {
606 607 608
        virReportSystemError(NULL, errno,
                             _("loading host definition file '%s'"),
                             file);
609
        goto error;
610 611
    }

612 613 614
    if (!(xml = xmlReadFd(fd, file, NULL,
                          XML_PARSE_NOENT | XML_PARSE_NONET |
                          XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
615 616
        testError(NULL, VIR_ERR_INTERNAL_ERROR,
                  _("Invalid XML in file '%s'"), file);
617
        goto error;
618
    }
619 620
    close(fd);
    fd = -1;
621

622 623
    root = xmlDocGetRootElement(xml);
    if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "node"))) {
624 625
        testError(NULL, VIR_ERR_XML_ERROR, "%s",
                  _("Root element is not 'node'"));
626
        goto error;
627 628
    }

629 630
    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
C
Cole Robinson 已提交
631 632
        testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s",
                  _("creating xpath context"));
633
        goto error;
634
    }
635

636
    privconn->nextDomID = 1;
637
    privconn->numCells = 0;
C
Chris Lalancette 已提交
638 639 640 641 642
    if (virStrcpyStatic(privconn->path, file) == NULL) {
        testError(NULL, VIR_ERR_INTERNAL_ERROR,
                  _("Path %s too big for destination"), file);
        goto error;
    }
643 644 645
    memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));

    nodeInfo = &privconn->nodeInfo;
646
    ret = virXPathLong(conn, "string(/node/cpu/nodes[1])", ctxt, &l);
647 648 649
    if (ret == 0) {
        nodeInfo->nodes = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
650
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu numa nodes"));
651
        goto error;
652
    }
653

654
    ret = virXPathLong(conn, "string(/node/cpu/sockets[1])", ctxt, &l);
655 656 657
    if (ret == 0) {
        nodeInfo->sockets = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
658
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu sockets"));
659
        goto error;
660
    }
661

662
    ret = virXPathLong(conn, "string(/node/cpu/cores[1])", ctxt, &l);
663 664 665
    if (ret == 0) {
        nodeInfo->cores = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
666
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu cores"));
667
        goto error;
668 669
    }

670
    ret = virXPathLong(conn, "string(/node/cpu/threads[1])", ctxt, &l);
671 672 673
    if (ret == 0) {
        nodeInfo->threads = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
674
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu threads"));
675
        goto error;
676
    }
677

678
    nodeInfo->cpus = nodeInfo->cores * nodeInfo->threads * nodeInfo->sockets * nodeInfo->nodes;
679
    ret = virXPathLong(conn, "string(/node/cpu/active[1])", ctxt, &l);
680 681
    if (ret == 0) {
        if (l < nodeInfo->cpus) {
682 683
            nodeInfo->cpus = l;
        }
684
    } else if (ret == -2) {
J
Jim Meyering 已提交
685
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node active cpu"));
686
        goto error;
687
    }
688
    ret = virXPathLong(conn, "string(/node/cpu/mhz[1])", ctxt, &l);
689 690 691
    if (ret == 0) {
        nodeInfo->mhz = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
692
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu mhz"));
693
        goto error;
694 695
    }

696
    str = virXPathString(conn, "string(/node/cpu/model[1])", ctxt);
697
    if (str != NULL) {
C
Chris Lalancette 已提交
698 699 700 701 702 703
        if (virStrcpyStatic(nodeInfo->model, str) == NULL) {
            testError(NULL, VIR_ERR_INTERNAL_ERROR,
                      _("Model %s too big for destination"), str);
            VIR_FREE(str);
            goto error;
        }
704
        VIR_FREE(str);
705 706
    }

707
    ret = virXPathLong(conn, "string(/node/memory[1])", ctxt, &l);
708 709 710
    if (ret == 0) {
        nodeInfo->memory = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
711
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node memory"));
712
        goto error;
713
    }
714

715
    ret = virXPathNodeSet(conn, "/node/domain", ctxt, &domains);
716
    if (ret < 0) {
J
Jim Meyering 已提交
717
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node domain list"));
718
        goto error;
719
    }
720

721
    for (i = 0 ; i < ret ; i++) {
722 723 724 725 726 727
        virDomainDefPtr def;
        char *relFile = virXMLPropString(domains[i], "file");
        if (relFile != NULL) {
            char *absFile = testBuildFilename(file, relFile);
            VIR_FREE(relFile);
            if (!absFile) {
J
Jim Meyering 已提交
728
                testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("resolving domain filename"));
729 730
                goto error;
            }
731 732
            def = virDomainDefParseFile(conn, privconn->caps, absFile,
                                        VIR_DOMAIN_XML_INACTIVE);
733
            VIR_FREE(absFile);
734 735 736
            if (!def)
                goto error;
        } else {
737 738
            if ((def = virDomainDefParseNode(conn, privconn->caps, xml, domains[i],
                                   VIR_DOMAIN_XML_INACTIVE)) == NULL)
739 740 741
                goto error;
        }

742
        if (testDomainGenerateIfnames(conn, def) < 0 ||
743 744
            !(dom = virDomainAssignDef(conn, privconn->caps,
                                       &privconn->domains, def))) {
745
            virDomainDefFree(def);
746 747
            goto error;
        }
748 749 750 751

        dom->state = VIR_DOMAIN_RUNNING;
        dom->def->id = privconn->nextDomID++;
        dom->persistent = 1;
752
        virDomainObjUnlock(dom);
753
    }
754
    VIR_FREE(domains);
755

756
    ret = virXPathNodeSet(conn, "/node/network", ctxt, &networks);
757
    if (ret < 0) {
J
Jim Meyering 已提交
758
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node network list"));
759 760 761 762 763 764 765 766
        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);
767
            if (!absFile) {
J
Jim Meyering 已提交
768
                testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("resolving network filename"));
769 770
                goto error;
            }
771 772

            def = virNetworkDefParseFile(conn, absFile);
773
            VIR_FREE(absFile);
774 775 776 777 778
            if (!def)
                goto error;
        } else {
            if ((def = virNetworkDefParseNode(conn, xml, networks[i])) == NULL)
                goto error;
779
        }
780 781 782 783
        if (!(net = virNetworkAssignDef(conn, &privconn->networks,
                                        def))) {
            virNetworkDefFree(def);
            goto error;
784
        }
785
        net->persistent = 1;
786
        net->active = 1;
787
        virNetworkObjUnlock(net);
788
    }
789
    VIR_FREE(networks);
790

L
Laine Stump 已提交
791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812
    /* Parse interface definitions */
    ret = virXPathNodeSet(conn, "/node/interface", ctxt, &ifaces);
    if (ret < 0) {
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node interface list"));
        goto error;
    }
    for (i = 0 ; i < ret ; i++) {
        virInterfaceDefPtr def;
        char *relFile = virXMLPropString(ifaces[i], "file");
        if (relFile != NULL) {
            char *absFile = testBuildFilename(file, relFile);
            VIR_FREE(relFile);
            if (!absFile) {
                testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("resolving interface filename"));
                goto error;
            }

            def = virInterfaceDefParseFile(conn, absFile);
            VIR_FREE(absFile);
            if (!def)
                goto error;
        } else {
813
            if ((def = virInterfaceDefParseNode(conn, xml, ifaces[i])) == NULL)
L
Laine Stump 已提交
814 815
                goto error;
        }
816

L
Laine Stump 已提交
817 818 819 820
        if (!(iface = virInterfaceAssignDef(conn, &privconn->ifaces, def))) {
            virInterfaceDefFree(def);
            goto error;
        }
821 822

        iface->active = 1;
L
Laine Stump 已提交
823 824 825 826
        virInterfaceObjUnlock(iface);
    }
    VIR_FREE(ifaces);

C
Cole Robinson 已提交
827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845
    /* 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;
            }

846
            def = virStoragePoolDefParseFile(conn, absFile);
C
Cole Robinson 已提交
847 848 849 850
            VIR_FREE(absFile);
            if (!def)
                goto error;
        } else {
851 852
            if ((def = virStoragePoolDefParseNode(conn, xml,
                                                  pools[i])) == NULL) {
C
Cole Robinson 已提交
853 854 855 856 857 858 859 860 861 862
                goto error;
            }
        }

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

863
        if (testStoragePoolObjSetDefaults(conn, pool) == -1) {
864
            virStoragePoolObjUnlock(pool);
C
Cole Robinson 已提交
865
            goto error;
866
        }
C
Cole Robinson 已提交
867
        pool->active = 1;
868 869 870 871 872 873 874

        /* Find storage volumes */
        if (testOpenVolumesForPool(conn, xml, ctxt, file, pool, i+1) < 0) {
            virStoragePoolObjUnlock(pool);
            goto error;
        }

875
        virStoragePoolObjUnlock(pool);
C
Cole Robinson 已提交
876
    }
877
    VIR_FREE(pools);
C
Cole Robinson 已提交
878

879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915
    ret = virXPathNodeSet(conn, "/node/device", ctxt, &devs);
    if (ret < 0) {
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node device list"));
        goto error;
    }
    for (i = 0 ; i < ret ; i++) {
        virNodeDeviceDefPtr def;
        virNodeDeviceObjPtr dev;
        char *relFile = virXMLPropString(devs[i], "file");

        if (relFile != NULL) {
            char *absFile = testBuildFilename(file, relFile);
            VIR_FREE(relFile);

            if (!absFile) {
                testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s",
                          _("resolving device filename"));
                goto error;
            }

            def = virNodeDeviceDefParseFile(conn, absFile, 0);
            VIR_FREE(absFile);
            if (!def)
                goto error;
        } else {
            if ((def = virNodeDeviceDefParseNode(conn, xml, devs[i], 0)) == NULL)
                goto error;
        }
        if (!(dev = virNodeDeviceAssignDef(conn, &privconn->devs, def))) {
            virNodeDeviceDefFree(def);
            goto error;
        }
        virNodeDeviceObjUnlock(dev);
    }
    VIR_FREE(devs);


J
Jim Meyering 已提交
916
    xmlXPathFreeContext(ctxt);
917
    xmlFreeDoc(xml);
918
    testDriverUnlock(privconn);
919

920
    return (0);
921 922

 error:
J
Jim Meyering 已提交
923
    xmlXPathFreeContext(ctxt);
924
    xmlFreeDoc(xml);
925 926
    VIR_FREE(domains);
    VIR_FREE(networks);
L
Laine Stump 已提交
927
    VIR_FREE(ifaces);
C
Cole Robinson 已提交
928
    VIR_FREE(pools);
929 930
    if (fd != -1)
        close(fd);
931
    virDomainObjListDeinit(&privconn->domains);
932
    virNetworkObjListFree(&privconn->networks);
L
Laine Stump 已提交
933
    virInterfaceObjListFree(&privconn->ifaces);
C
Cole Robinson 已提交
934
    virStoragePoolObjListFree(&privconn->pools);
935
    testDriverUnlock(privconn);
936
    VIR_FREE(privconn);
937
    conn->privateData = NULL;
938
    return VIR_DRV_OPEN_ERROR;
939 940
}

941

942
static virDrvOpenStatus testOpen(virConnectPtr conn,
943
                    virConnectAuthPtr auth ATTRIBUTE_UNUSED,
944
                    int flags ATTRIBUTE_UNUSED)
945
{
946
    int ret;
947

948
    if (!conn->uri)
949
        return VIR_DRV_OPEN_DECLINED;
950

951
    if (!conn->uri->scheme || STRNEQ(conn->uri->scheme, "test"))
952
        return VIR_DRV_OPEN_DECLINED;
953

954
    /* Remote driver should handle these. */
955
    if (conn->uri->server)
956 957
        return VIR_DRV_OPEN_DECLINED;

958
    /* From this point on, the connection is for us. */
959 960 961
    if (!conn->uri->path
        || conn->uri->path[0] == '\0'
        || (conn->uri->path[0] == '/' && conn->uri->path[1] == '\0')) {
962
        testError (NULL, VIR_ERR_INVALID_ARG,
J
Jim Meyering 已提交
963
                   "%s", _("testOpen: supply a path or use test:///default"));
964 965
        return VIR_DRV_OPEN_ERROR;
    }
966

967
    if (STREQ(conn->uri->path, "/default"))
968 969
        ret = testOpenDefault(conn);
    else
970
        ret = testOpenFromFile(conn,
971
                               conn->uri->path);
972

973 974
    if (ret == VIR_DRV_OPEN_SUCCESS) {
        testConnPtr privconn = conn->privateData;
975
        testDriverLock(privconn);
976 977 978 979
        /* Init callback list */
        if (VIR_ALLOC(privconn->domainEventCallbacks) < 0 ||
            !(privconn->domainEventQueue = virDomainEventQueueNew())) {
            virReportOOMError(NULL);
980
            testDriverUnlock(privconn);
981 982 983 984 985 986 987 988
            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.");
989
        testDriverUnlock(privconn);
990 991
    }

992
    return (ret);
993 994
}

995
static int testClose(virConnectPtr conn)
996
{
997
    testConnPtr privconn = conn->privateData;
998
    testDriverLock(privconn);
999
    virCapabilitiesFree(privconn->caps);
1000
    virDomainObjListDeinit(&privconn->domains);
1001
    virNetworkObjListFree(&privconn->networks);
L
Laine Stump 已提交
1002
    virInterfaceObjListFree(&privconn->ifaces);
C
Cole Robinson 已提交
1003
    virStoragePoolObjListFree(&privconn->pools);
1004 1005 1006 1007 1008 1009 1010

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

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

1011
    testDriverUnlock(privconn);
1012
    virMutexDestroy(&privconn->lock);
1013

1014
    VIR_FREE (privconn);
1015
    conn->privateData = NULL;
1016
    return 0;
1017 1018
}

1019 1020
static int testGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
                          unsigned long *hvVer)
1021
{
1022 1023
    *hvVer = 2;
    return (0);
1024 1025
}

1026
static char *testGetHostname (virConnectPtr conn)
1027
{
1028
    char *result;
1029

1030 1031
    result = virGetHostname();
    if (result == NULL) {
1032 1033
        virReportSystemError(conn, errno,
                             "%s", _("cannot lookup hostname"));
1034 1035
        return NULL;
    }
1036 1037
    /* Caller frees this string. */
    return result;
1038 1039
}

1040 1041 1042 1043 1044 1045 1046 1047
static int testGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED,
                           const char *type ATTRIBUTE_UNUSED)
{
    return 32;
}

static int testNodeGetInfo(virConnectPtr conn,
                           virNodeInfoPtr info)
1048
{
1049
    testConnPtr privconn = conn->privateData;
1050
    testDriverLock(privconn);
1051
    memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo));
1052
    testDriverUnlock(privconn);
1053
    return (0);
1054 1055
}

1056
static char *testGetCapabilities (virConnectPtr conn)
1057
{
1058
    testConnPtr privconn = conn->privateData;
1059
    char *xml;
1060
    testDriverLock(privconn);
1061
    if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL)
1062
        virReportOOMError(conn);
1063
    testDriverUnlock(privconn);
1064
    return xml;
1065 1066
}

1067
static int testNumOfDomains(virConnectPtr conn)
1068
{
1069
    testConnPtr privconn = conn->privateData;
1070
    int count;
1071

1072
    testDriverLock(privconn);
1073
    count = virDomainObjListNumOfDomains(&privconn->domains, 1);
1074
    testDriverUnlock(privconn);
1075

1076
    return count;
1077 1078
}

1079
static virDomainPtr
1080
testDomainCreateXML(virConnectPtr conn, const char *xml,
1081
                      unsigned int flags ATTRIBUTE_UNUSED)
1082
{
1083
    testConnPtr privconn = conn->privateData;
1084
    virDomainPtr ret = NULL;
1085
    virDomainDefPtr def;
1086
    virDomainObjPtr dom = NULL;
1087
    virDomainEventPtr event = NULL;
1088

1089
    testDriverLock(privconn);
1090 1091
    if ((def = virDomainDefParseString(conn, privconn->caps, xml,
                                       VIR_DOMAIN_XML_INACTIVE)) == NULL)
1092
        goto cleanup;
1093

1094
    if (testDomainGenerateIfnames(conn, def) < 0)
1095
        goto cleanup;
1096 1097
    if (!(dom = virDomainAssignDef(conn, privconn->caps,
                                   &privconn->domains, def)))
1098 1099
        goto cleanup;
    def = NULL;
1100 1101
    dom->state = VIR_DOMAIN_RUNNING;
    dom->def->id = privconn->nextDomID++;
1102

1103 1104 1105 1106
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);

1107
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1108
    if (ret)
1109
        ret->id = dom->def->id;
1110 1111

cleanup:
1112 1113
    if (dom)
        virDomainObjUnlock(dom);
1114 1115
    if (event)
        testDomainEventQueue(privconn, event);
1116 1117
    if (def)
        virDomainDefFree(def);
1118
    testDriverUnlock(privconn);
1119
    return ret;
1120 1121 1122
}


1123 1124
static virDomainPtr testLookupDomainByID(virConnectPtr conn,
                                         int id)
1125
{
1126
    testConnPtr privconn = conn->privateData;
1127 1128
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1129

1130 1131 1132 1133 1134
    testDriverLock(privconn);
    dom = virDomainFindByID(&privconn->domains, id);
    testDriverUnlock(privconn);

    if (dom == NULL) {
1135
        testError (conn, VIR_ERR_NO_DOMAIN, NULL);
1136
        goto cleanup;
1137 1138
    }

1139
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1140 1141 1142 1143
    if (ret)
        ret->id = dom->def->id;

cleanup:
1144 1145
    if (dom)
        virDomainObjUnlock(dom);
1146
    return ret;
1147 1148
}

1149 1150
static virDomainPtr testLookupDomainByUUID(virConnectPtr conn,
                                           const unsigned char *uuid)
1151
{
1152
    testConnPtr privconn = conn->privateData;
1153 1154
    virDomainPtr ret = NULL;
    virDomainObjPtr dom ;
1155

1156 1157 1158 1159 1160
    testDriverLock(privconn);
    dom = virDomainFindByUUID(&privconn->domains, uuid);
    testDriverUnlock(privconn);

    if (dom == NULL) {
1161
        testError (conn, VIR_ERR_NO_DOMAIN, NULL);
1162
        goto cleanup;
1163
    }
1164

1165
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1166 1167 1168 1169
    if (ret)
        ret->id = dom->def->id;

cleanup:
1170 1171
    if (dom)
        virDomainObjUnlock(dom);
1172
    return ret;
1173 1174
}

1175 1176
static virDomainPtr testLookupDomainByName(virConnectPtr conn,
                                           const char *name)
1177
{
1178
    testConnPtr privconn = conn->privateData;
1179 1180
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1181

1182 1183 1184 1185 1186
    testDriverLock(privconn);
    dom = virDomainFindByName(&privconn->domains, name);
    testDriverUnlock(privconn);

    if (dom == NULL) {
1187
        testError (conn, VIR_ERR_NO_DOMAIN, NULL);
1188
        goto cleanup;
1189
    }
1190

1191
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1192 1193 1194 1195
    if (ret)
        ret->id = dom->def->id;

cleanup:
1196 1197
    if (dom)
        virDomainObjUnlock(dom);
1198
    return ret;
1199 1200
}

1201 1202 1203
static int testListDomains (virConnectPtr conn,
                            int *ids,
                            int maxids)
1204
{
1205
    testConnPtr privconn = conn->privateData;
1206
    int n;
1207

1208
    testDriverLock(privconn);
1209
    n = virDomainObjListGetActiveIDs(&privconn->domains, ids, maxids);
1210
    testDriverUnlock(privconn);
1211

1212
    return n;
1213 1214
}

1215
static int testDestroyDomain (virDomainPtr domain)
1216
{
1217 1218
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1219
    virDomainEventPtr event = NULL;
1220
    int ret = -1;
1221

1222
    testDriverLock(privconn);
1223 1224 1225 1226 1227
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1228
        goto cleanup;
1229
    }
1230

1231
    privdom->state = VIR_DOMAIN_SHUTOFF;
1232 1233
    privdom->def->id = -1;
    domain->id = -1;
1234 1235 1236
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
1237 1238 1239
    if (!privdom->persistent) {
        virDomainRemoveInactive(&privconn->domains,
                                privdom);
1240
        privdom = NULL;
1241
    }
1242

1243

1244 1245
    ret = 0;
cleanup:
1246 1247
    if (privdom)
        virDomainObjUnlock(privdom);
1248 1249
    if (event)
        testDomainEventQueue(privconn, event);
1250
    testDriverUnlock(privconn);
1251
    return ret;
1252 1253
}

1254
static int testResumeDomain (virDomainPtr domain)
1255
{
1256 1257
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1258
    virDomainEventPtr event = NULL;
1259
    int ret = -1;
1260

1261
    testDriverLock(privconn);
1262 1263
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1264
    testDriverUnlock(privconn);
1265 1266 1267

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1268
        goto cleanup;
1269
    }
1270

1271
    if (privdom->state != VIR_DOMAIN_PAUSED) {
1272 1273 1274
        testError(domain->conn,
                  VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"),
                  domain->name);
1275
        goto cleanup;
1276
    }
1277

1278
    privdom->state = VIR_DOMAIN_RUNNING;
1279 1280 1281
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_RESUMED,
                                     VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
1282 1283 1284
    ret = 0;

cleanup:
1285 1286
    if (privdom)
        virDomainObjUnlock(privdom);
1287 1288 1289 1290 1291
    if (event) {
        testDriverLock(privconn);
        testDomainEventQueue(privconn, event);
        testDriverUnlock(privconn);
    }
1292
    return ret;
1293 1294
}

1295
static int testPauseDomain (virDomainPtr domain)
1296
{
1297 1298
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1299
    virDomainEventPtr event = NULL;
1300
    int ret = -1;
1301

1302
    testDriverLock(privconn);
1303 1304
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1305
    testDriverUnlock(privconn);
1306 1307 1308

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1309
        goto cleanup;
1310
    }
1311

1312 1313
    if (privdom->state == VIR_DOMAIN_SHUTOFF ||
        privdom->state == VIR_DOMAIN_PAUSED) {
1314 1315 1316
        testError(domain->conn,
                  VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"),
                  domain->name);
1317
        goto cleanup;
1318
    }
1319

1320
    privdom->state = VIR_DOMAIN_PAUSED;
1321 1322 1323
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_SUSPENDED,
                                     VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
1324 1325 1326
    ret = 0;

cleanup:
1327 1328
    if (privdom)
        virDomainObjUnlock(privdom);
1329 1330 1331 1332 1333 1334

    if (event) {
        testDriverLock(privconn);
        testDomainEventQueue(privconn, event);
        testDriverUnlock(privconn);
    }
1335
    return ret;
1336 1337
}

1338
static int testShutdownDomain (virDomainPtr domain)
1339
{
1340 1341
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1342
    virDomainEventPtr event = NULL;
1343
    int ret = -1;
1344

1345
    testDriverLock(privconn);
1346 1347 1348 1349 1350
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1351
        goto cleanup;
1352
    }
1353

1354
    if (privdom->state == VIR_DOMAIN_SHUTOFF) {
1355 1356
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("domain '%s' not running"), domain->name);
1357
        goto cleanup;
1358
    }
1359

1360
    privdom->state = VIR_DOMAIN_SHUTOFF;
1361
    domain->id = -1;
1362
    privdom->def->id = -1;
1363 1364 1365
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1366 1367 1368 1369 1370
    if (!privdom->persistent) {
        virDomainRemoveInactive(&privconn->domains,
                                privdom);
        privdom = NULL;
    }
1371
    ret = 0;
1372

1373
cleanup:
1374 1375
    if (privdom)
        virDomainObjUnlock(privdom);
1376 1377
    if (event)
        testDomainEventQueue(privconn, event);
1378
    testDriverUnlock(privconn);
1379
    return ret;
1380 1381 1382
}

/* Similar behaviour as shutdown */
1383 1384
static int testRebootDomain (virDomainPtr domain,
                             unsigned int action ATTRIBUTE_UNUSED)
1385
{
1386 1387
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1388
    virDomainEventPtr event = NULL;
1389
    int ret = -1;
1390

1391
    testDriverLock(privconn);
1392 1393 1394 1395 1396
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1397
        goto cleanup;
1398
    }
1399

1400 1401 1402 1403
    privdom->state = VIR_DOMAIN_SHUTDOWN;
    switch (privdom->def->onReboot) {
    case VIR_DOMAIN_LIFECYCLE_DESTROY:
        privdom->state = VIR_DOMAIN_SHUTOFF;
1404
        domain->id = -1;
1405
        privdom->def->id = -1;
1406 1407
        break;

1408 1409
    case VIR_DOMAIN_LIFECYCLE_RESTART:
        privdom->state = VIR_DOMAIN_RUNNING;
1410 1411
        break;

1412 1413
    case VIR_DOMAIN_LIFECYCLE_PRESERVE:
        privdom->state = VIR_DOMAIN_SHUTOFF;
1414
        domain->id = -1;
1415
        privdom->def->id = -1;
1416 1417
        break;

1418 1419
    case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME:
        privdom->state = VIR_DOMAIN_RUNNING;
1420
        break;
1421

1422
    default:
1423
        privdom->state = VIR_DOMAIN_SHUTOFF;
1424
        domain->id = -1;
1425
        privdom->def->id = -1;
1426 1427
        break;
    }
1428

1429 1430 1431 1432 1433 1434 1435 1436 1437
    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;
        }
1438 1439
    }

1440 1441 1442
    ret = 0;

cleanup:
1443 1444
    if (privdom)
        virDomainObjUnlock(privdom);
1445 1446
    if (event)
        testDomainEventQueue(privconn, event);
1447
    testDriverUnlock(privconn);
1448
    return ret;
1449 1450
}

1451 1452
static int testGetDomainInfo (virDomainPtr domain,
                              virDomainInfoPtr info)
1453
{
1454
    testConnPtr privconn = domain->conn->privateData;
1455
    struct timeval tv;
1456
    virDomainObjPtr privdom;
1457
    int ret = -1;
1458

1459
    testDriverLock(privconn);
1460 1461
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1462
    testDriverUnlock(privconn);
1463 1464 1465

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1466
        goto cleanup;
1467
    }
1468 1469

    if (gettimeofday(&tv, NULL) < 0) {
1470
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1471
                  "%s", _("getting time of day"));
1472
        goto cleanup;
1473 1474
    }

1475 1476 1477 1478 1479
    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));
1480 1481 1482
    ret = 0;

cleanup:
1483 1484
    if (privdom)
        virDomainObjUnlock(privdom);
1485
    return ret;
1486 1487
}

1488 1489 1490 1491 1492
#define TEST_SAVE_MAGIC "TestGuestMagic"

static int testDomainSave(virDomainPtr domain,
                          const char *path)
{
1493
    testConnPtr privconn = domain->conn->privateData;
1494 1495 1496
    char *xml = NULL;
    int fd = -1;
    int len;
1497
    virDomainObjPtr privdom;
1498
    virDomainEventPtr event = NULL;
1499
    int ret = -1;
1500

1501
    testDriverLock(privconn);
1502 1503 1504 1505 1506
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1507
        goto cleanup;
1508
    }
1509

C
Cole Robinson 已提交
1510 1511 1512 1513
    xml = virDomainDefFormat(domain->conn,
                             privdom->def,
                             VIR_DOMAIN_XML_SECURE);

1514
    if (xml == NULL) {
1515 1516 1517
        virReportSystemError(domain->conn, errno,
                             _("saving domain '%s' failed to allocate space for metadata"),
                             domain->name);
1518
        goto cleanup;
1519
    }
1520 1521

    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
1522 1523 1524
        virReportSystemError(domain->conn, errno,
                             _("saving domain '%s' to '%s': open failed"),
                             domain->name, path);
1525
        goto cleanup;
1526
    }
1527
    len = strlen(xml);
1528
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
1529 1530 1531
        virReportSystemError(domain->conn, errno,
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1532
        goto cleanup;
1533
    }
1534
    if (safewrite(fd, (char*)&len, sizeof(len)) < 0) {
1535 1536 1537
        virReportSystemError(domain->conn, errno,
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1538
        goto cleanup;
1539
    }
1540
    if (safewrite(fd, xml, len) < 0) {
1541 1542 1543
        virReportSystemError(domain->conn, errno,
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1544
        goto cleanup;
1545
    }
1546

1547
    if (close(fd) < 0) {
1548 1549 1550
        virReportSystemError(domain->conn, errno,
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1551
        goto cleanup;
1552
    }
1553 1554
    fd = -1;

1555
    privdom->state = VIR_DOMAIN_SHUTOFF;
1556 1557 1558
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
1559 1560 1561
    if (!privdom->persistent) {
        virDomainRemoveInactive(&privconn->domains,
                                privdom);
1562
        privdom = NULL;
1563
    }
1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576
    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);
    }
1577 1578
    if (privdom)
        virDomainObjUnlock(privdom);
1579 1580
    if (event)
        testDomainEventQueue(privconn, event);
1581
    testDriverUnlock(privconn);
1582
    return ret;
1583 1584
}

1585 1586
static int testDomainRestore(virConnectPtr conn,
                             const char *path)
1587
{
1588
    testConnPtr privconn = conn->privateData;
1589
    char *xml = NULL;
1590
    char magic[15];
1591 1592 1593
    int fd = -1;
    int len;
    virDomainDefPtr def = NULL;
1594
    virDomainObjPtr dom = NULL;
1595
    virDomainEventPtr event = NULL;
1596
    int ret = -1;
1597 1598

    if ((fd = open(path, O_RDONLY)) < 0) {
1599 1600 1601
        virReportSystemError(conn, errno,
                             _("cannot read domain image '%s'"),
                             path);
1602
        goto cleanup;
1603
    }
1604 1605 1606 1607
    if (saferead(fd, magic, sizeof(magic)) != sizeof(magic)) {
        virReportSystemError(conn, errno,
                             _("incomplete save header in '%s'"),
                             path);
1608
        goto cleanup;
1609
    }
1610
    if (memcmp(magic, TEST_SAVE_MAGIC, sizeof(magic))) {
1611
        testError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1612
                  "%s", _("mismatched header magic"));
1613
        goto cleanup;
1614
    }
1615 1616 1617 1618
    if (saferead(fd, (char*)&len, sizeof(len)) != sizeof(len)) {
        virReportSystemError(conn, errno,
                             _("failed to read metadata length in '%s'"),
                             path);
1619
        goto cleanup;
1620 1621
    }
    if (len < 1 || len > 8192) {
1622
        testError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1623
                  "%s", _("length of metadata out of range"));
1624
        goto cleanup;
1625
    }
1626
    if (VIR_ALLOC_N(xml, len+1) < 0) {
1627
        virReportOOMError(conn);
1628
        goto cleanup;
1629
    }
1630 1631 1632
    if (saferead(fd, xml, len) != len) {
        virReportSystemError(conn, errno,
                             _("incomplete metdata in '%s'"), path);
1633
        goto cleanup;
1634 1635
    }
    xml[len] = '\0';
1636

1637
    testDriverLock(privconn);
1638 1639
    def = virDomainDefParseString(conn, privconn->caps, xml,
                                  VIR_DOMAIN_XML_INACTIVE);
1640
    if (!def)
1641
        goto cleanup;
1642

1643
    if (testDomainGenerateIfnames(conn, def) < 0)
1644
        goto cleanup;
1645 1646
    if (!(dom = virDomainAssignDef(conn, privconn->caps,
                                   &privconn->domains, def)))
1647 1648
        goto cleanup;
    def = NULL;
1649

1650 1651
    dom->state = VIR_DOMAIN_RUNNING;
    dom->def->id = privconn->nextDomID++;
1652 1653 1654
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
1655
    ret = 0;
1656 1657 1658 1659 1660 1661

cleanup:
    virDomainDefFree(def);
    VIR_FREE(xml);
    if (fd != -1)
        close(fd);
1662 1663
    if (dom)
        virDomainObjUnlock(dom);
1664 1665
    if (event)
        testDomainEventQueue(privconn, event);
1666
    testDriverUnlock(privconn);
1667
    return ret;
1668 1669
}

1670 1671 1672
static int testDomainCoreDump(virDomainPtr domain,
                              const char *to,
                              int flags ATTRIBUTE_UNUSED)
1673
{
1674
    testConnPtr privconn = domain->conn->privateData;
1675
    int fd = -1;
1676
    virDomainObjPtr privdom;
1677
    virDomainEventPtr event = NULL;
1678
    int ret = -1;
1679

1680
    testDriverLock(privconn);
1681 1682 1683 1684 1685
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

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

    if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
1690 1691 1692
        virReportSystemError(domain->conn, errno,
                             _("domain '%s' coredump: failed to open %s"),
                             domain->name, to);
1693
        goto cleanup;
1694
    }
1695
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
1696 1697 1698
        virReportSystemError(domain->conn, errno,
                             _("domain '%s' coredump: failed to write header to %s"),
                             domain->name, to);
1699
        goto cleanup;
1700
    }
1701
    if (close(fd) < 0) {
1702 1703 1704
        virReportSystemError(domain->conn, errno,
                             _("domain '%s' coredump: write failed: %s"),
                             domain->name, to);
1705
        goto cleanup;
1706
    }
1707
    privdom->state = VIR_DOMAIN_SHUTOFF;
1708 1709 1710
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_CRASHED);
1711 1712 1713
    if (!privdom->persistent) {
        virDomainRemoveInactive(&privconn->domains,
                                privdom);
1714
        privdom = NULL;
1715
    }
1716 1717 1718 1719 1720
    ret = 0;

cleanup:
    if (fd != -1)
        close(fd);
1721 1722
    if (privdom)
        virDomainObjUnlock(privdom);
1723 1724
    if (event)
        testDomainEventQueue(privconn, event);
1725
    testDriverUnlock(privconn);
1726
    return ret;
1727 1728
}

1729 1730 1731
static char *testGetOSType(virDomainPtr dom) {
    char *ret = strdup("linux");
    if (!ret)
1732
        virReportOOMError(dom->conn);
1733
    return ret;
1734 1735 1736
}

static unsigned long testGetMaxMemory(virDomainPtr domain) {
1737 1738
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1739
    unsigned long ret = 0;
1740

1741
    testDriverLock(privconn);
1742 1743
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1744
    testDriverUnlock(privconn);
1745 1746 1747

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1748
        goto cleanup;
1749
    }
1750

1751 1752 1753
    ret = privdom->def->maxmem;

cleanup:
1754 1755
    if (privdom)
        virDomainObjUnlock(privdom);
1756
    return ret;
1757 1758 1759 1760 1761
}

static int testSetMaxMemory(virDomainPtr domain,
                            unsigned long memory)
{
1762 1763
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1764
    int ret = -1;
1765

1766
    testDriverLock(privconn);
1767 1768
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1769
    testDriverUnlock(privconn);
1770 1771 1772

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1773
        goto cleanup;
1774
    }
1775 1776

    /* XXX validate not over host memory wrt to other domains */
1777
    privdom->def->maxmem = memory;
1778 1779 1780
    ret = 0;

cleanup:
1781 1782
    if (privdom)
        virDomainObjUnlock(privdom);
1783
    return ret;
1784 1785
}

1786 1787 1788
static int testSetMemory(virDomainPtr domain,
                         unsigned long memory)
{
1789 1790
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1791
    int ret = -1;
1792

1793
    testDriverLock(privconn);
1794 1795
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1796
    testDriverUnlock(privconn);
1797 1798 1799

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1800
        goto cleanup;
1801
    }
1802

1803
    if (memory > privdom->def->maxmem) {
1804
        testError(domain->conn,
1805
                  VIR_ERR_INVALID_ARG, __FUNCTION__);
1806
        goto cleanup;
1807
    }
1808

1809
    privdom->def->memory = memory;
1810 1811 1812
    ret = 0;

cleanup:
1813 1814
    if (privdom)
        virDomainObjUnlock(privdom);
1815
    return ret;
1816 1817 1818 1819
}

static int testSetVcpus(virDomainPtr domain,
                        unsigned int nrCpus) {
1820 1821
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1822 1823
    int ret = -1;

1824 1825 1826 1827 1828 1829
    testDriverLock(privconn);
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
    testDriverUnlock(privconn);

    if (privdom == NULL) {
1830
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1831
        goto cleanup;
1832
    }
1833

1834 1835
    /* We allow more cpus in guest than host */
    if (nrCpus > 32) {
1836
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1837
        goto cleanup;
1838
    }
1839

1840
    privdom->def->vcpus = nrCpus;
1841 1842 1843
    ret = 0;

cleanup:
1844 1845
    if (privdom)
        virDomainObjUnlock(privdom);
1846
    return ret;
1847 1848
}

1849
static char *testDomainDumpXML(virDomainPtr domain, int flags)
1850
{
1851
    testConnPtr privconn = domain->conn->privateData;
1852
    virDomainDefPtr def;
1853
    virDomainObjPtr privdom;
1854 1855
    char *ret = NULL;

1856 1857 1858 1859 1860 1861
    testDriverLock(privconn);
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
    testDriverUnlock(privconn);

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

1866 1867
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
1868

1869 1870 1871 1872 1873
    ret = virDomainDefFormat(domain->conn,
                             def,
                             flags);

cleanup:
1874 1875
    if (privdom)
        virDomainObjUnlock(privdom);
1876
    return ret;
1877
}
1878

1879
static int testNumOfDefinedDomains(virConnectPtr conn) {
1880
    testConnPtr privconn = conn->privateData;
1881
    int count;
1882

1883
    testDriverLock(privconn);
1884
    count = virDomainObjListNumOfDomains(&privconn->domains, 0);
1885
    testDriverUnlock(privconn);
1886

1887
    return count;
1888 1889
}

1890 1891 1892
static int testListDefinedDomains(virConnectPtr conn,
                                  char **const names,
                                  int maxnames) {
1893

1894
    testConnPtr privconn = conn->privateData;
1895
    int n;
1896

1897
    testDriverLock(privconn);
1898
    memset(names, 0, sizeof(*names)*maxnames);
1899
    n = virDomainObjListGetInactiveNames(&privconn->domains, names, maxnames);
1900
    testDriverUnlock(privconn);
1901

1902
    return n;
1903 1904
}

1905
static virDomainPtr testDomainDefineXML(virConnectPtr conn,
1906
                                        const char *xml) {
1907
    testConnPtr privconn = conn->privateData;
1908
    virDomainPtr ret = NULL;
1909
    virDomainDefPtr def;
1910
    virDomainObjPtr dom = NULL;
1911
    virDomainEventPtr event = NULL;
1912

1913
    testDriverLock(privconn);
1914 1915
    if ((def = virDomainDefParseString(conn, privconn->caps, xml,
                                       VIR_DOMAIN_XML_INACTIVE)) == NULL)
1916
        goto cleanup;
1917

1918 1919
    if (testDomainGenerateIfnames(conn, def) < 0)
        goto cleanup;
1920 1921
    if (!(dom = virDomainAssignDef(conn, privconn->caps,
                                   &privconn->domains, def)))
1922
        goto cleanup;
1923
    def = NULL;
1924
    dom->persistent = 1;
1925

1926 1927 1928
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_DEFINED,
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED);
1929

1930
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1931
    if (ret)
1932
        ret->id = dom->def->id;
1933 1934 1935

cleanup:
    virDomainDefFree(def);
1936 1937
    if (dom)
        virDomainObjUnlock(dom);
1938 1939
    if (event)
        testDomainEventQueue(privconn, event);
1940
    testDriverUnlock(privconn);
1941
    return ret;
1942 1943
}

1944 1945 1946
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
                                      int startCell, int maxCells) {
1947
    testConnPtr privconn = conn->privateData;
1948
    int i, j;
1949
    int ret = -1;
1950

1951
    testDriverLock(privconn);
1952
    if (startCell > privconn->numCells) {
1953
        testError(conn, VIR_ERR_INVALID_ARG,
J
Jim Meyering 已提交
1954
                  "%s", _("Range exceeds available cells"));
1955
        goto cleanup;
1956 1957 1958 1959 1960 1961 1962
    }

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

1965
cleanup:
1966
    testDriverUnlock(privconn);
1967
    return ret;
1968 1969 1970
}


1971
static int testDomainCreate(virDomainPtr domain) {
1972 1973
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1974
    virDomainEventPtr event = NULL;
1975
    int ret = -1;
1976

1977
    testDriverLock(privconn);
1978 1979 1980 1981 1982
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1983
        goto cleanup;
1984
    }
1985

1986
    if (privdom->state != VIR_DOMAIN_SHUTOFF) {
1987 1988
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Domain '%s' is already running"), domain->name);
1989
        goto cleanup;
1990 1991
    }

1992 1993
    domain->id = privdom->def->id = privconn->nextDomID++;
    privdom->state = VIR_DOMAIN_RUNNING;
1994 1995 1996
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
1997
    ret = 0;
1998

1999
cleanup:
2000 2001
    if (privdom)
        virDomainObjUnlock(privdom);
2002 2003
    if (event)
        testDomainEventQueue(privconn, event);
2004
    testDriverUnlock(privconn);
2005
    return ret;
2006 2007 2008
}

static int testDomainUndefine(virDomainPtr domain) {
2009 2010
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2011
    virDomainEventPtr event = NULL;
2012
    int ret = -1;
2013

2014
    testDriverLock(privconn);
2015 2016 2017 2018 2019
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2020
        goto cleanup;
2021
    }
2022

2023
    if (privdom->state != VIR_DOMAIN_SHUTOFF) {
2024 2025
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Domain '%s' is still running"), domain->name);
2026
        goto cleanup;
2027 2028
    }

2029
    privdom->state = VIR_DOMAIN_SHUTOFF;
2030 2031 2032
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
2033 2034
    virDomainRemoveInactive(&privconn->domains,
                            privdom);
2035
    privdom = NULL;
2036
    ret = 0;
2037

2038
cleanup:
2039 2040
    if (privdom)
        virDomainObjUnlock(privdom);
2041 2042
    if (event)
        testDomainEventQueue(privconn, event);
2043
    testDriverUnlock(privconn);
2044
    return ret;
2045 2046
}

2047 2048 2049
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
2050 2051
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2052
    int ret = -1;
2053

2054
    testDriverLock(privconn);
2055 2056
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
2057
    testDriverUnlock(privconn);
2058 2059 2060

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2061
        goto cleanup;
2062 2063
    }

2064
    *autostart = privdom->autostart;
2065 2066 2067
    ret = 0;

cleanup:
2068 2069
    if (privdom)
        virDomainObjUnlock(privdom);
2070
    return ret;
2071 2072 2073 2074 2075 2076
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
2077 2078
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2079
    int ret = -1;
2080

2081
    testDriverLock(privconn);
2082 2083
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
2084
    testDriverUnlock(privconn);
2085 2086 2087

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2088
        goto cleanup;
2089 2090
    }

2091
    privdom->autostart = autostart ? 1 : 0;
2092 2093 2094
    ret = 0;

cleanup:
2095 2096
    if (privdom)
        virDomainObjUnlock(privdom);
2097
    return ret;
2098
}
2099

2100 2101 2102
static char *testDomainGetSchedulerType(virDomainPtr domain,
                                        int *nparams)
{
2103 2104
    char *type = NULL;

2105 2106
    *nparams = 1;
    type = strdup("fair");
2107
    if (!type)
2108
        virReportOOMError(domain->conn);
2109

2110 2111 2112 2113 2114 2115 2116
    return type;
}

static int testDomainGetSchedulerParams(virDomainPtr domain,
                                        virSchedParameterPtr params,
                                        int *nparams)
{
2117 2118
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2119
    int ret = -1;
2120

2121
    testDriverLock(privconn);
2122 2123
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
2124
    testDriverUnlock(privconn);
2125 2126 2127

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2128
        goto cleanup;
2129 2130
    }

2131
    if (*nparams != 1) {
2132
        testError(domain->conn, VIR_ERR_INVALID_ARG, "nparams");
2133
        goto cleanup;
2134
    }
2135 2136
    strcpy(params[0].field, "weight");
    params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT;
2137 2138 2139
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
    params[0].value.ui = 50;
2140 2141 2142
    ret = 0;

cleanup:
2143 2144
    if (privdom)
        virDomainObjUnlock(privdom);
2145
    return ret;
2146
}
2147 2148


2149 2150 2151 2152
static int testDomainSetSchedulerParams(virDomainPtr domain,
                                        virSchedParameterPtr params,
                                        int nparams)
{
2153 2154
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2155
    int ret = -1;
2156

2157
    testDriverLock(privconn);
2158 2159
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
2160
    testDriverUnlock(privconn);
2161 2162 2163

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2164
        goto cleanup;
2165 2166
    }

2167
    if (nparams != 1) {
2168
        testError(domain->conn, VIR_ERR_INVALID_ARG, "nparams");
2169
        goto cleanup;
2170
    }
2171
    if (STRNEQ(params[0].field, "weight")) {
2172
        testError(domain->conn, VIR_ERR_INVALID_ARG, "field");
2173
        goto cleanup;
2174 2175
    }
    if (params[0].type != VIR_DOMAIN_SCHED_FIELD_UINT) {
2176
        testError(domain->conn, VIR_ERR_INVALID_ARG, "type");
2177
        goto cleanup;
2178
    }
2179 2180
    /* XXX */
    /*privdom->weight = params[0].value.ui;*/
2181 2182 2183
    ret = 0;

cleanup:
2184 2185
    if (privdom)
        virDomainObjUnlock(privdom);
2186
    return ret;
2187 2188
}

2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300
static int testDomainBlockStats(virDomainPtr domain,
                                const char *path,
                                struct _virDomainBlockStats *stats)
{
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
    int i, found = 0, ret = -1;

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

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
        goto error;
    }

    for (i = 0 ; i < privdom->def->ndisks ; i++) {
        if (STREQ(path, privdom->def->disks[i]->dst)) {
            found = 1;
            break;
        }
    }

    if (!found) {
        testError(domain->conn, VIR_ERR_INVALID_ARG,
                  _("invalid path: %s"), path);
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
        virReportSystemError(domain->conn, errno,
                             "%s", _("getting time of day"));
        goto error;
    }

    /* No significance to these numbers, just enough to mix it up*/
    statbase = (tv.tv_sec * 1000UL * 1000UL) + tv.tv_usec;
    stats->rd_req = statbase / 10;
    stats->rd_bytes = statbase / 20;
    stats->wr_req = statbase / 30;
    stats->wr_bytes = statbase / 40;
    stats->errs = tv.tv_sec / 2;

    ret = 0;
error:
    if (privdom)
        virDomainObjUnlock(privdom);
    return ret;
}

static int testDomainInterfaceStats(virDomainPtr domain,
                                    const char *path,
                                    struct _virDomainInterfaceStats *stats)
{
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
    int i, found = 0, ret = -1;

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

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
        goto error;
    }

    for (i = 0 ; i < privdom->def->nnets ; i++) {
        if (privdom->def->nets[i]->ifname &&
            STREQ (privdom->def->nets[i]->ifname, path)) {
            found = 1;
            break;
        }
    }

    if (!found) {
        testError(domain->conn, VIR_ERR_INVALID_ARG,
                  _("invalid path, '%s' is not a known interface"), path);
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
        virReportSystemError(domain->conn, errno,
                             "%s", _("getting time of day"));
        goto error;
    }

    /* No significance to these numbers, just enough to mix it up*/
    statbase = (tv.tv_sec * 1000UL * 1000UL) + tv.tv_usec;
    stats->rx_bytes = statbase / 10;
    stats->rx_packets = statbase / 100;
    stats->rx_errs = tv.tv_sec / 1;
    stats->rx_drop = tv.tv_sec / 2;
    stats->tx_bytes = statbase / 20;
    stats->tx_packets = statbase / 110;
    stats->tx_errs = tv.tv_sec / 3;
    stats->tx_drop = tv.tv_sec / 4;

    ret = 0;
error:
    if (privdom)
        virDomainObjUnlock(privdom);
    return ret;
}

2301
static virDrvOpenStatus testOpenNetwork(virConnectPtr conn,
2302
                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319
                                        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)
{
2320 2321
    testConnPtr privconn = conn->privateData;
    virNetworkObjPtr net;
2322
    virNetworkPtr ret = NULL;
2323

2324 2325 2326 2327 2328
    testDriverLock(privconn);
    net = virNetworkFindByUUID(&privconn->networks, uuid);
    testDriverUnlock(privconn);

    if (net == NULL) {
2329
        testError (conn, VIR_ERR_NO_NETWORK, NULL);
2330
        goto cleanup;
2331 2332
    }

2333 2334 2335
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

cleanup:
2336 2337
    if (net)
        virNetworkObjUnlock(net);
2338
    return ret;
2339
}
2340

2341
static virNetworkPtr testLookupNetworkByName(virConnectPtr conn,
2342
                                             const char *name)
2343
{
2344
    testConnPtr privconn = conn->privateData;
2345 2346
    virNetworkObjPtr net;
    virNetworkPtr ret = NULL;
2347

2348 2349 2350 2351 2352
    testDriverLock(privconn);
    net = virNetworkFindByName(&privconn->networks, name);
    testDriverUnlock(privconn);

    if (net == NULL) {
2353
        testError (conn, VIR_ERR_NO_NETWORK, NULL);
2354
        goto cleanup;
2355 2356
    }

2357 2358 2359
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

cleanup:
2360 2361
    if (net)
        virNetworkObjUnlock(net);
2362
    return ret;
2363 2364 2365 2366
}


static int testNumNetworks(virConnectPtr conn) {
2367
    testConnPtr privconn = conn->privateData;
2368
    int numActive = 0, i;
2369

2370 2371 2372
    testDriverLock(privconn);
    for (i = 0 ; i < privconn->networks.count ; i++) {
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
2373
        if (virNetworkObjIsActive(privconn->networks.objs[i]))
2374
            numActive++;
2375 2376 2377
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
2378

2379
    return numActive;
2380 2381 2382
}

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

2386
    testDriverLock(privconn);
2387
    memset(names, 0, sizeof(*names)*nnames);
2388 2389
    for (i = 0 ; i < privconn->networks.count && n < nnames ; i++) {
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
2390
        if (virNetworkObjIsActive(privconn->networks.objs[i]) &&
2391 2392
            !(names[n++] = strdup(privconn->networks.objs[i]->def->name))) {
            virNetworkObjUnlock(privconn->networks.objs[i]);
2393
            goto no_memory;
2394 2395 2396 2397
        }
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
2398

2399 2400 2401
    return n;

no_memory:
2402
    virReportOOMError(conn);
2403 2404
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
2405
    testDriverUnlock(privconn);
2406
    return -1;
2407 2408 2409
}

static int testNumDefinedNetworks(virConnectPtr conn) {
2410
    testConnPtr privconn = conn->privateData;
2411
    int numInactive = 0, i;
2412

2413 2414 2415
    testDriverLock(privconn);
    for (i = 0 ; i < privconn->networks.count ; i++) {
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
2416
        if (!virNetworkObjIsActive(privconn->networks.objs[i]))
2417
            numInactive++;
2418 2419 2420
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
2421

2422
    return numInactive;
2423 2424 2425
}

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

2429
    testDriverLock(privconn);
2430
    memset(names, 0, sizeof(*names)*nnames);
2431 2432
    for (i = 0 ; i < privconn->networks.count && n < nnames ; i++) {
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
2433
        if (!virNetworkObjIsActive(privconn->networks.objs[i]) &&
2434 2435
            !(names[n++] = strdup(privconn->networks.objs[i]->def->name))) {
            virNetworkObjUnlock(privconn->networks.objs[i]);
2436
            goto no_memory;
2437 2438 2439 2440
        }
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
2441

2442 2443 2444
    return n;

no_memory:
2445
    virReportOOMError(conn);
2446 2447
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
2448
    testDriverUnlock(privconn);
2449
    return -1;
2450 2451 2452
}

static virNetworkPtr testNetworkCreate(virConnectPtr conn, const char *xml) {
2453
    testConnPtr privconn = conn->privateData;
2454
    virNetworkDefPtr def;
2455
    virNetworkObjPtr net = NULL;
2456
    virNetworkPtr ret = NULL;
2457

2458
    testDriverLock(privconn);
2459
    if ((def = virNetworkDefParseString(conn, xml)) == NULL)
2460
        goto cleanup;
2461

2462
    if ((net = virNetworkAssignDef(conn, &privconn->networks, def)) == NULL)
2463 2464
        goto cleanup;
    def = NULL;
2465
    net->active = 1;
2466

2467
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
2468

2469 2470
cleanup:
    virNetworkDefFree(def);
2471 2472 2473
    if (net)
        virNetworkObjUnlock(net);
    testDriverUnlock(privconn);
2474
    return ret;
2475 2476 2477
}

static virNetworkPtr testNetworkDefine(virConnectPtr conn, const char *xml) {
2478
    testConnPtr privconn = conn->privateData;
2479
    virNetworkDefPtr def;
2480
    virNetworkObjPtr net = NULL;
2481
    virNetworkPtr ret = NULL;
2482

2483
    testDriverLock(privconn);
2484
    if ((def = virNetworkDefParseString(conn, xml)) == NULL)
2485
        goto cleanup;
2486

2487
    if ((net = virNetworkAssignDef(conn, &privconn->networks, def)) == NULL)
2488 2489
        goto cleanup;
    def = NULL;
2490
    net->persistent = 1;
2491

2492
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
2493 2494 2495

cleanup:
    virNetworkDefFree(def);
2496 2497 2498
    if (net)
        virNetworkObjUnlock(net);
    testDriverUnlock(privconn);
2499
    return ret;
2500 2501 2502
}

static int testNetworkUndefine(virNetworkPtr network) {
2503 2504
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
2505
    int ret = -1;
2506

2507
    testDriverLock(privconn);
2508 2509 2510 2511 2512
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2513
        goto cleanup;
2514
    }
2515

D
Daniel P. Berrange 已提交
2516
    if (virNetworkObjIsActive(privnet)) {
2517 2518
        testError(network->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Network '%s' is still running"), network->name);
2519
        goto cleanup;
2520 2521
    }

2522 2523
    virNetworkRemoveInactive(&privconn->networks,
                             privnet);
2524
    privnet = NULL;
2525
    ret = 0;
2526

2527
cleanup:
2528 2529 2530
    if (privnet)
        virNetworkObjUnlock(privnet);
    testDriverUnlock(privconn);
2531
    return ret;
2532 2533 2534
}

static int testNetworkStart(virNetworkPtr network) {
2535 2536
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
2537
    int ret = -1;
2538

2539
    testDriverLock(privconn);
2540 2541
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
2542
    testDriverUnlock(privconn);
2543 2544 2545

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2546
        goto cleanup;
2547
    }
2548

D
Daniel P. Berrange 已提交
2549
    if (virNetworkObjIsActive(privnet)) {
2550 2551
        testError(network->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Network '%s' is already running"), network->name);
2552
        goto cleanup;
2553 2554
    }

2555
    privnet->active = 1;
2556
    ret = 0;
2557

2558
cleanup:
2559 2560
    if (privnet)
        virNetworkObjUnlock(privnet);
2561
    return ret;
2562 2563 2564
}

static int testNetworkDestroy(virNetworkPtr network) {
2565 2566
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
2567
    int ret = -1;
2568

2569
    testDriverLock(privconn);
2570 2571 2572 2573 2574
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2575
        goto cleanup;
2576
    }
2577

2578 2579 2580 2581
    privnet->active = 0;
    if (!privnet->persistent) {
        virNetworkRemoveInactive(&privconn->networks,
                                 privnet);
2582
        privnet = NULL;
2583
    }
2584 2585 2586
    ret = 0;

cleanup:
2587 2588 2589
    if (privnet)
        virNetworkObjUnlock(privnet);
    testDriverUnlock(privconn);
2590
    return ret;
2591 2592 2593
}

static char *testNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) {
2594 2595
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
2596
    char *ret = NULL;
2597

2598
    testDriverLock(privconn);
2599 2600
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
2601
    testDriverUnlock(privconn);
2602 2603 2604

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2605
        goto cleanup;
2606
    }
2607

2608 2609 2610
    ret = virNetworkDefFormat(network->conn, privnet->def);

cleanup:
2611 2612
    if (privnet)
        virNetworkObjUnlock(privnet);
2613
    return ret;
2614 2615 2616
}

static char *testNetworkGetBridgeName(virNetworkPtr network) {
2617
    testConnPtr privconn = network->conn->privateData;
2618
    char *bridge = NULL;
2619 2620
    virNetworkObjPtr privnet;

2621
    testDriverLock(privconn);
2622 2623
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
2624
    testDriverUnlock(privconn);
2625 2626 2627

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2628
        goto cleanup;
2629 2630
    }

2631 2632 2633 2634 2635 2636 2637 2638
    if (!(privnet->def->bridge)) {
        testError(network->conn, VIR_ERR_INTERNAL_ERROR,
                  _("network '%s' does not have a bridge name."),
                  privnet->def->name);
        goto cleanup;
    }

    if (!(bridge = strdup(privnet->def->bridge))) {
2639
        virReportOOMError(network->conn);
2640
        goto cleanup;
2641
    }
2642 2643

cleanup:
2644 2645
    if (privnet)
        virNetworkObjUnlock(privnet);
2646 2647 2648 2649 2650
    return bridge;
}

static int testNetworkGetAutostart(virNetworkPtr network,
                                   int *autostart) {
2651 2652
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
2653
    int ret = -1;
2654

2655
    testDriverLock(privconn);
2656 2657
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
2658
    testDriverUnlock(privconn);
2659 2660 2661

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2662
        goto cleanup;
2663 2664
    }

2665
    *autostart = privnet->autostart;
2666 2667 2668
    ret = 0;

cleanup:
2669 2670
    if (privnet)
        virNetworkObjUnlock(privnet);
2671
    return ret;
2672 2673 2674 2675
}

static int testNetworkSetAutostart(virNetworkPtr network,
                                   int autostart) {
2676 2677
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
2678
    int ret = -1;
2679

2680
    testDriverLock(privconn);
2681 2682
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
2683
    testDriverUnlock(privconn);
2684 2685 2686

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2687
        goto cleanup;
2688 2689
    }

2690
    privnet->autostart = autostart ? 1 : 0;
2691 2692 2693
    ret = 0;

cleanup:
2694 2695
    if (privnet)
        virNetworkObjUnlock(privnet);
2696
    return ret;
2697
}
2698

C
Cole Robinson 已提交
2699

L
Laine Stump 已提交
2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729
/*
 * Physical host interface routines
 */

static virDrvOpenStatus testOpenInterface(virConnectPtr conn,
                                          virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                          int flags ATTRIBUTE_UNUSED)
{
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

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

static int testCloseInterface(virConnectPtr conn)
{
    conn->interfacePrivateData = NULL;
    return 0;
}


static int testNumOfInterfaces(virConnectPtr conn)
{
    testConnPtr privconn = conn->privateData;
    int i, count = 0;

    testDriverLock(privconn);
    for (i = 0 ; (i < privconn->ifaces.count); i++) {
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
2730
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
L
Laine Stump 已提交
2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747
            count++;
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

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

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
    for (i = 0 ; (i < privconn->ifaces.count) && (n < nnames); i++) {
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
2748
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
L
Laine Stump 已提交
2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775
            if (!(names[n++] = strdup(privconn->ifaces.objs[i]->def->name))) {
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
                goto no_memory;
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

no_memory:
    virReportOOMError(conn);
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

static int testNumOfDefinedInterfaces(virConnectPtr conn)
{
    testConnPtr privconn = conn->privateData;
    int i, count = 0;

    testDriverLock(privconn);
    for (i = 0 ; i < privconn->ifaces.count; i++) {
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
2776
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
L
Laine Stump 已提交
2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793
            count++;
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

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

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
    for (i = 0 ; (i < privconn->ifaces.count) && (n < nnames); i++) {
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
2794
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
L
Laine Stump 已提交
2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007
            if (!(names[n++] = strdup(privconn->ifaces.objs[i]->def->name))) {
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
                goto no_memory;
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

no_memory:
    virReportOOMError(conn);
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

static virInterfacePtr testLookupInterfaceByName(virConnectPtr conn,
                                                 const char *name)
{
    testConnPtr privconn = conn->privateData;
    virInterfaceObjPtr iface;
    virInterfacePtr ret = NULL;

    testDriverLock(privconn);
    iface = virInterfaceFindByName(&privconn->ifaces, name);
    testDriverUnlock(privconn);

    if (iface == NULL) {
        testError (conn, VIR_ERR_NO_INTERFACE, NULL);
        goto cleanup;
    }

    ret = virGetInterface(conn, iface->def->name, iface->def->mac);

cleanup:
    if (iface)
        virInterfaceObjUnlock(iface);
    return ret;
}

static virInterfacePtr testLookupInterfaceByMACString(virConnectPtr conn,
                                                      const char *mac)
{
    testConnPtr privconn = conn->privateData;
    virInterfaceObjPtr iface;
    int ifacect;
    virInterfacePtr ret = NULL;

    testDriverLock(privconn);
    ifacect = virInterfaceFindByMACString(&privconn->ifaces, mac, &iface, 1);
    testDriverUnlock(privconn);

    if (ifacect == 0) {
        testError (conn, VIR_ERR_NO_INTERFACE, NULL);
        goto cleanup;
    }

    if (ifacect > 1) {
        testError (conn, VIR_ERR_MULTIPLE_INTERFACES, NULL);
        goto cleanup;
    }

    ret = virGetInterface(conn, iface->def->name, iface->def->mac);

cleanup:
    if (iface)
        virInterfaceObjUnlock(iface);
    return ret;
}

static char *testInterfaceGetXMLDesc(virInterfacePtr iface,
                                     unsigned int flags ATTRIBUTE_UNUSED)
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr privinterface;
    char *ret = NULL;

    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);
    testDriverUnlock(privconn);

    if (privinterface == NULL) {
        testError(iface->conn, VIR_ERR_NO_INTERFACE, __FUNCTION__);
        goto cleanup;
    }

    ret = virInterfaceDefFormat(iface->conn, privinterface->def);

cleanup:
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    return ret;
}


static virInterfacePtr testInterfaceDefineXML(virConnectPtr conn, const char *xmlStr,
                                              unsigned int flags ATTRIBUTE_UNUSED)
{
    testConnPtr privconn = conn->privateData;
    virInterfaceDefPtr def;
    virInterfaceObjPtr iface = NULL;
    virInterfacePtr ret = NULL;

    testDriverLock(privconn);
    if ((def = virInterfaceDefParseString(conn, xmlStr)) == NULL)
        goto cleanup;

    if ((iface = virInterfaceAssignDef(conn, &privconn->ifaces, def)) == NULL)
        goto cleanup;
    def = NULL;

    ret = virGetInterface(conn, iface->def->name, iface->def->mac);

cleanup:
    virInterfaceDefFree(def);
    if (iface)
        virInterfaceObjUnlock(iface);
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceUndefine(virInterfacePtr iface)
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr privinterface;
    int ret = -1;

    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);

    if (privinterface == NULL) {
        testError (iface->conn, VIR_ERR_NO_INTERFACE, NULL);
        goto cleanup;
    }

    virInterfaceRemove(&privconn->ifaces,
                       privinterface);
    ret = 0;

cleanup:
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceCreate(virInterfacePtr iface,
                               unsigned int flags ATTRIBUTE_UNUSED)
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr privinterface;
    int ret = -1;

    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);

    if (privinterface == NULL) {
        testError (iface->conn, VIR_ERR_NO_INTERFACE, NULL);
        goto cleanup;
    }

    if (privinterface->active != 0) {
        testError (iface->conn, VIR_ERR_OPERATION_INVALID, NULL);
        goto cleanup;
    }

    privinterface->active = 1;
    ret = 0;

cleanup:
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceDestroy(virInterfacePtr iface,
                                unsigned int flags ATTRIBUTE_UNUSED)
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr privinterface;
    int ret = -1;

    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);

    if (privinterface == NULL) {
        testError (iface->conn, VIR_ERR_NO_INTERFACE, NULL);
        goto cleanup;
    }

    if (privinterface->active == 0) {
        testError (iface->conn, VIR_ERR_OPERATION_INVALID, NULL);
        goto cleanup;
    }

    privinterface->active = 0;
    ret = 0;

cleanup:
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    testDriverUnlock(privconn);
    return ret;
}



C
Cole Robinson 已提交
3008 3009 3010 3011
/*
 * Storage Driver routines
 */

3012 3013
static int testStoragePoolObjSetDefaults(virConnectPtr conn,
                                         virStoragePoolObjPtr pool) {
C
Cole Robinson 已提交
3014 3015 3016 3017 3018 3019 3020

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

    pool->configFile = strdup("\0");
    if (!pool->configFile) {
3021
        virReportOOMError(conn);
C
Cole Robinson 已提交
3022 3023 3024 3025 3026 3027
        return -1;
    }

    return 0;
}

3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042
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 已提交
3043 3044 3045
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
                            const unsigned char *uuid) {
3046
    testConnPtr privconn = conn->privateData;
3047 3048
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3049

3050
    testDriverLock(privconn);
3051
    pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid);
3052
    testDriverUnlock(privconn);
3053 3054

    if (pool == NULL) {
C
Cole Robinson 已提交
3055
        testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL);
3056
        goto cleanup;
C
Cole Robinson 已提交
3057 3058
    }

3059 3060 3061
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
3062 3063
    if (pool)
        virStoragePoolObjUnlock(pool);
3064
    return ret;
C
Cole Robinson 已提交
3065 3066 3067 3068 3069
}

static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
                            const char *name) {
3070
    testConnPtr privconn = conn->privateData;
3071 3072
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3073

3074
    testDriverLock(privconn);
3075
    pool = virStoragePoolObjFindByName(&privconn->pools, name);
3076
    testDriverUnlock(privconn);
3077 3078

    if (pool == NULL) {
C
Cole Robinson 已提交
3079
        testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL);
3080
        goto cleanup;
C
Cole Robinson 已提交
3081 3082
    }

3083 3084 3085
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
3086 3087
    if (pool)
        virStoragePoolObjUnlock(pool);
3088
    return ret;
C
Cole Robinson 已提交
3089 3090 3091 3092 3093 3094 3095 3096 3097
}

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

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

3101
    testDriverLock(privconn);
C
Cole Robinson 已提交
3102 3103 3104
    for (i = 0 ; i < privconn->pools.count ; i++)
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numActive++;
3105
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3106 3107 3108 3109 3110 3111 3112 3113

    return numActive;
}

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

3117
    testDriverLock(privconn);
C
Cole Robinson 已提交
3118
    memset(names, 0, sizeof(*names)*nnames);
3119 3120
    for (i = 0 ; i < privconn->pools.count && n < nnames ; i++) {
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3121
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
3122 3123
            !(names[n++] = strdup(privconn->pools.objs[i]->def->name))) {
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3124
            goto no_memory;
3125 3126 3127 3128
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3129 3130 3131 3132

    return n;

no_memory:
3133
    virReportOOMError(conn);
C
Cole Robinson 已提交
3134 3135
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
3136
    testDriverUnlock(privconn);
3137
    return -1;
C
Cole Robinson 已提交
3138 3139 3140 3141
}

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

3145 3146 3147
    testDriverLock(privconn);
    for (i = 0 ; i < privconn->pools.count ; i++) {
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3148 3149
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numInactive++;
3150 3151 3152
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3153 3154 3155 3156 3157 3158 3159 3160

    return numInactive;
}

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

3164
    testDriverLock(privconn);
C
Cole Robinson 已提交
3165
    memset(names, 0, sizeof(*names)*nnames);
3166 3167
    for (i = 0 ; i < privconn->pools.count && n < nnames ; i++) {
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3168
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
3169 3170
            !(names[n++] = strdup(privconn->pools.objs[i]->def->name))) {
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3171
            goto no_memory;
3172 3173 3174 3175
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3176 3177 3178 3179

    return n;

no_memory:
3180
    virReportOOMError(conn);
C
Cole Robinson 已提交
3181 3182
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
3183
    testDriverUnlock(privconn);
3184
    return -1;
C
Cole Robinson 已提交
3185 3186 3187 3188
}


static int
3189
testStoragePoolStart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3190
                     unsigned int flags ATTRIBUTE_UNUSED) {
3191 3192
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3193
    int ret = -1;
3194

3195
    testDriverLock(privconn);
3196 3197
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3198
    testDriverUnlock(privconn);
3199 3200 3201

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

3205 3206 3207 3208 3209
    if (virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is already active"), pool->name);
        goto cleanup;
    }
C
Cole Robinson 已提交
3210 3211

    privpool->active = 1;
3212
    ret = 0;
C
Cole Robinson 已提交
3213

3214
cleanup:
3215 3216
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3217
    return ret;
C
Cole Robinson 已提交
3218 3219 3220
}

static char *
3221 3222 3223
testStorageFindPoolSources(virConnectPtr conn,
                           const char *type,
                           const char *srcSpec,
C
Cole Robinson 已提交
3224 3225
                           unsigned int flags ATTRIBUTE_UNUSED)
{
3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270
    virStoragePoolSourcePtr source = NULL;
    int pool_type;
    char *ret = NULL;

    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
        testError(conn, VIR_ERR_INTERNAL_ERROR,
                  _("unknown storage pool type %s"), type);
        goto cleanup;
    }

    if (srcSpec) {
        source = virStoragePoolDefParseSourceString(conn, srcSpec, pool_type);
        if (!source)
            goto cleanup;
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
        ret = strdup(defaultPoolSourcesLogicalXML);
        if (!ret)
            virReportOOMError(conn);
        break;

    case VIR_STORAGE_POOL_NETFS:
        if (!source || !source->host.name) {
            testError(conn, VIR_ERR_INVALID_ARG,
                      "%s", "hostname must be specified for netfs sources");
            goto cleanup;
        }

        if (virAsprintf(&ret, defaultPoolSourcesNetFSXML,
                        source->host.name) < 0)
            virReportOOMError(conn);
        break;

    default:
        testError(conn, VIR_ERR_NO_SUPPORT,
                  _("pool type '%s' does not support source discovery"), type);
    }

cleanup:
    virStoragePoolSourceFree(source);
    return ret;
C
Cole Robinson 已提交
3271 3272 3273 3274 3275 3276 3277
}


static virStoragePoolPtr
testStoragePoolCreate(virConnectPtr conn,
                      const char *xml,
                      unsigned int flags ATTRIBUTE_UNUSED) {
3278
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
3279
    virStoragePoolDefPtr def;
3280
    virStoragePoolObjPtr pool = NULL;
3281
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3282

3283
    testDriverLock(privconn);
3284
    if (!(def = virStoragePoolDefParseString(conn, xml)))
3285
        goto cleanup;
C
Cole Robinson 已提交
3286

3287 3288 3289 3290
    pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid);
    if (!pool)
        pool = virStoragePoolObjFindByName(&privconn->pools, def->name);
    if (pool) {
C
Cole Robinson 已提交
3291 3292
        testError(conn, VIR_ERR_INTERNAL_ERROR,
                  "%s", _("storage pool already exists"));
3293
        goto cleanup;
C
Cole Robinson 已提交
3294 3295
    }

3296
    if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, def)))
3297
        goto cleanup;
3298
    def = NULL;
C
Cole Robinson 已提交
3299

3300
    if (testStoragePoolObjSetDefaults(conn, pool) == -1) {
C
Cole Robinson 已提交
3301
        virStoragePoolObjRemove(&privconn->pools, pool);
3302 3303
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
3304 3305 3306
    }
    pool->active = 1;

3307 3308 3309 3310
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
    virStoragePoolDefFree(def);
3311 3312 3313
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
3314
    return ret;
C
Cole Robinson 已提交
3315 3316 3317 3318 3319 3320
}

static virStoragePoolPtr
testStoragePoolDefine(virConnectPtr conn,
                      const char *xml,
                      unsigned int flags ATTRIBUTE_UNUSED) {
3321
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
3322
    virStoragePoolDefPtr def;
3323
    virStoragePoolObjPtr pool = NULL;
3324
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3325

3326
    testDriverLock(privconn);
3327
    if (!(def = virStoragePoolDefParseString(conn, xml)))
3328
        goto cleanup;
C
Cole Robinson 已提交
3329 3330 3331 3332 3333

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

3334
    if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, def)))
3335 3336
        goto cleanup;
    def = NULL;
C
Cole Robinson 已提交
3337

3338
    if (testStoragePoolObjSetDefaults(conn, pool) == -1) {
C
Cole Robinson 已提交
3339
        virStoragePoolObjRemove(&privconn->pools, pool);
3340 3341
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
3342 3343
    }

3344 3345 3346 3347
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
    virStoragePoolDefFree(def);
3348 3349 3350
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
3351
    return ret;
C
Cole Robinson 已提交
3352 3353 3354
}

static int
3355 3356 3357
testStoragePoolUndefine(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3358
    int ret = -1;
3359

3360
    testDriverLock(privconn);
3361 3362 3363 3364 3365
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

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

3369 3370 3371 3372 3373
    if (virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is already active"), pool->name);
        goto cleanup;
    }
C
Cole Robinson 已提交
3374 3375

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

3378
cleanup:
3379 3380 3381
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
3382
    return ret;
C
Cole Robinson 已提交
3383 3384 3385
}

static int
3386
testStoragePoolBuild(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3387
                     unsigned int flags ATTRIBUTE_UNUSED) {
3388 3389
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3390
    int ret = -1;
3391

3392
    testDriverLock(privconn);
3393 3394
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3395
    testDriverUnlock(privconn);
3396 3397 3398

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

3402 3403 3404 3405 3406
    if (virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is already active"), pool->name);
        goto cleanup;
    }
3407
    ret = 0;
C
Cole Robinson 已提交
3408

3409
cleanup:
3410 3411
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3412
    return ret;
C
Cole Robinson 已提交
3413 3414 3415 3416
}


static int
3417 3418 3419
testStoragePoolDestroy(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3420
    int ret = -1;
3421

3422
    testDriverLock(privconn);
3423 3424 3425 3426 3427
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3428
        goto cleanup;
3429 3430 3431 3432 3433
    }

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

    privpool->active = 0;

3439
    if (privpool->configFile == NULL) {
C
Cole Robinson 已提交
3440
        virStoragePoolObjRemove(&privconn->pools, privpool);
3441 3442
        privpool = NULL;
    }
3443
    ret = 0;
C
Cole Robinson 已提交
3444

3445
cleanup:
3446 3447 3448
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
3449
    return ret;
C
Cole Robinson 已提交
3450 3451 3452 3453
}


static int
3454
testStoragePoolDelete(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3455
                      unsigned int flags ATTRIBUTE_UNUSED) {
3456 3457
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3458
    int ret = -1;
3459

3460
    testDriverLock(privconn);
3461 3462
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3463
    testDriverUnlock(privconn);
3464 3465 3466

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3467 3468 3469 3470 3471 3472 3473
        goto cleanup;
    }

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

3476
    ret = 0;
C
Cole Robinson 已提交
3477

3478
cleanup:
3479 3480
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3481
    return ret;
C
Cole Robinson 已提交
3482 3483 3484 3485
}


static int
3486
testStoragePoolRefresh(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3487
                       unsigned int flags ATTRIBUTE_UNUSED) {
3488 3489
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3490
    int ret = -1;
3491

3492
    testDriverLock(privconn);
3493 3494
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3495
    testDriverUnlock(privconn);
3496 3497 3498

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3499
        goto cleanup;
3500 3501 3502 3503 3504
    }

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

3509
cleanup:
3510 3511
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3512
    return ret;
C
Cole Robinson 已提交
3513 3514 3515 3516
}


static int
3517
testStoragePoolGetInfo(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3518
                       virStoragePoolInfoPtr info) {
3519 3520
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3521
    int ret = -1;
3522

3523
    testDriverLock(privconn);
3524 3525
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3526
    testDriverUnlock(privconn);
3527 3528 3529

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3530
        goto cleanup;
3531
    }
C
Cole Robinson 已提交
3532 3533 3534 3535 3536 3537 3538 3539 3540

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

3543
cleanup:
3544 3545
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3546
    return ret;
C
Cole Robinson 已提交
3547 3548 3549
}

static char *
3550
testStoragePoolDumpXML(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3551
                       unsigned int flags ATTRIBUTE_UNUSED) {
3552 3553
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3554
    char *ret = NULL;
3555

3556
    testDriverLock(privconn);
3557 3558
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3559
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3560

3561 3562
    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3563
        goto cleanup;
3564 3565
    }

3566 3567 3568
    ret = virStoragePoolDefFormat(pool->conn, privpool->def);

cleanup:
3569 3570
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3571
    return ret;
C
Cole Robinson 已提交
3572 3573 3574
}

static int
3575
testStoragePoolGetAutostart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3576
                            int *autostart) {
3577 3578
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3579
    int ret = -1;
3580

3581
    testDriverLock(privconn);
3582 3583
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3584
    testDriverUnlock(privconn);
3585 3586 3587

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3588
        goto cleanup;
3589
    }
C
Cole Robinson 已提交
3590 3591 3592 3593 3594 3595

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

3598
cleanup:
3599 3600
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3601
    return ret;
C
Cole Robinson 已提交
3602 3603 3604
}

static int
3605
testStoragePoolSetAutostart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3606
                            int autostart) {
3607 3608
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3609
    int ret = -1;
3610

3611
    testDriverLock(privconn);
3612 3613
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3614
    testDriverUnlock(privconn);
3615 3616 3617

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3618
        goto cleanup;
3619
    }
C
Cole Robinson 已提交
3620 3621

    if (!privpool->configFile) {
3622
        testError(pool->conn, VIR_ERR_INVALID_ARG,
C
Cole Robinson 已提交
3623
                  "%s", _("pool has no config file"));
3624
        goto cleanup;
C
Cole Robinson 已提交
3625 3626 3627 3628
    }

    autostart = (autostart != 0);
    privpool->autostart = autostart;
3629 3630 3631
    ret = 0;

cleanup:
3632 3633
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3634
    return ret;
C
Cole Robinson 已提交
3635 3636 3637 3638
}


static int
3639 3640 3641
testStoragePoolNumVolumes(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3642
    int ret = -1;
3643

3644
    testDriverLock(privconn);
3645 3646
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3647
    testDriverUnlock(privconn);
3648 3649 3650

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3651
        goto cleanup;
3652 3653 3654 3655 3656
    }

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

3660 3661 3662
    ret = privpool->volumes.count;

cleanup:
3663 3664
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3665
    return ret;
C
Cole Robinson 已提交
3666 3667 3668
}

static int
3669
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3670 3671
                           char **const names,
                           int maxnames) {
3672 3673
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
C
Cole Robinson 已提交
3674 3675
    int i = 0, n = 0;

3676
    memset(names, 0, maxnames * sizeof(*names));
3677 3678

    testDriverLock(privconn);
3679 3680
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3681
    testDriverUnlock(privconn);
3682 3683 3684

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3685
        goto cleanup;
3686 3687 3688 3689 3690 3691
    }


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

C
Cole Robinson 已提交
3695 3696
    for (i = 0 ; i < privpool->volumes.count && n < maxnames ; i++) {
        if ((names[n++] = strdup(privpool->volumes.objs[i]->name)) == NULL) {
3697
            virReportOOMError(pool->conn);
C
Cole Robinson 已提交
3698 3699 3700 3701
            goto cleanup;
        }
    }

3702
    virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
3703 3704 3705 3706 3707 3708
    return n;

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

3709
    memset(names, 0, maxnames * sizeof(*names));
3710 3711
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
3712 3713 3714 3715 3716
    return -1;
}


static virStorageVolPtr
3717
testStorageVolumeLookupByName(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3718
                              const char *name ATTRIBUTE_UNUSED) {
3719 3720 3721
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
3722
    virStorageVolPtr ret = NULL;
3723

3724
    testDriverLock(privconn);
3725 3726
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3727
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3728

3729 3730
    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3731
        goto cleanup;
3732 3733 3734 3735 3736 3737
    }


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

    privvol = virStorageVolDefFindByName(privpool, name);

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

3749 3750 3751 3752
    ret = virGetStorageVol(pool->conn, privpool->def->name,
                           privvol->name, privvol->key);

cleanup:
3753 3754
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3755
    return ret;
C
Cole Robinson 已提交
3756 3757 3758 3759 3760 3761
}


static virStorageVolPtr
testStorageVolumeLookupByKey(virConnectPtr conn,
                             const char *key) {
3762
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
3763
    unsigned int i;
3764
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
3765

3766
    testDriverLock(privconn);
C
Cole Robinson 已提交
3767
    for (i = 0 ; i < privconn->pools.count ; i++) {
3768
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3769
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
3770
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
3771 3772
                virStorageVolDefFindByKey(privconn->pools.objs[i], key);

3773 3774 3775 3776 3777
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
                                       privvol->key);
3778
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
3779 3780
                break;
            }
C
Cole Robinson 已提交
3781
        }
3782
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3783
    }
3784
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3785

3786 3787 3788 3789 3790
    if (!ret)
        testError(conn, VIR_ERR_INVALID_STORAGE_VOL,
                  _("no storage vol with matching key '%s'"), key);

    return ret;
C
Cole Robinson 已提交
3791 3792 3793 3794 3795
}

static virStorageVolPtr
testStorageVolumeLookupByPath(virConnectPtr conn,
                              const char *path) {
3796
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
3797
    unsigned int i;
3798
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
3799

3800
    testDriverLock(privconn);
C
Cole Robinson 已提交
3801
    for (i = 0 ; i < privconn->pools.count ; i++) {
3802
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3803
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
3804
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
3805 3806
                virStorageVolDefFindByPath(privconn->pools.objs[i], path);

3807 3808 3809 3810 3811
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
                                       privvol->key);
3812
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
3813 3814
                break;
            }
C
Cole Robinson 已提交
3815
        }
3816
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3817
    }
3818
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3819

3820 3821 3822 3823 3824
    if (!ret)
        testError(conn, VIR_ERR_INVALID_STORAGE_VOL,
                  _("no storage vol with matching path '%s'"), path);

    return ret;
C
Cole Robinson 已提交
3825 3826 3827
}

static virStorageVolPtr
3828
testStorageVolumeCreateXML(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3829 3830
                           const char *xmldesc,
                           unsigned int flags ATTRIBUTE_UNUSED) {
3831 3832
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3833 3834
    virStorageVolDefPtr privvol = NULL;
    virStorageVolPtr ret = NULL;
3835

3836
    testDriverLock(privconn);
3837 3838
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3839
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3840

3841 3842
    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3843
        goto cleanup;
3844 3845 3846 3847 3848
    }

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

3852
    privvol = virStorageVolDefParseString(pool->conn, privpool->def, xmldesc);
3853
    if (privvol == NULL)
3854
        goto cleanup;
3855 3856

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
3857
        testError(pool->conn, VIR_ERR_INVALID_STORAGE_VOL,
C
Cole Robinson 已提交
3858
                  "%s", _("storage vol already exists"));
3859
        goto cleanup;
C
Cole Robinson 已提交
3860 3861 3862
    }

    /* Make sure enough space */
3863
    if ((privpool->def->allocation + privvol->allocation) >
C
Cole Robinson 已提交
3864
         privpool->def->capacity) {
3865
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
C
Cole Robinson 已提交
3866
                  _("Not enough free space in pool for volume '%s'"),
3867
                  privvol->name);
3868
        goto cleanup;
C
Cole Robinson 已提交
3869 3870 3871 3872
    }

    if (VIR_REALLOC_N(privpool->volumes.objs,
                      privpool->volumes.count+1) < 0) {
3873
        virReportOOMError(pool->conn);
3874
        goto cleanup;
C
Cole Robinson 已提交
3875 3876
    }

3877 3878 3879
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
                    privvol->name) == -1) {
3880
        virReportOOMError(pool->conn);
3881
        goto cleanup;
C
Cole Robinson 已提交
3882 3883
    }

3884 3885
    privvol->key = strdup(privvol->target.path);
    if (privvol->key == NULL) {
3886
        virReportOOMError(pool->conn);
3887
        goto cleanup;
C
Cole Robinson 已提交
3888 3889
    }

3890
    privpool->def->allocation += privvol->allocation;
C
Cole Robinson 已提交
3891 3892 3893
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

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

3896 3897
    ret = virGetStorageVol(pool->conn, privpool->def->name,
                           privvol->name, privvol->key);
3898
    privvol = NULL;
3899 3900 3901

cleanup:
    virStorageVolDefFree(privvol);
3902 3903
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3904
    return ret;
C
Cole Robinson 已提交
3905 3906
}

3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932
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;
    }

3933
    privvol = virStorageVolDefParseString(pool->conn, privpool->def, xmldesc);
3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967
    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;
    }

3968 3969 3970
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
                    privvol->name) == -1) {
3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997
        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 已提交
3998
static int
3999
testStorageVolumeDelete(virStorageVolPtr vol,
C
Cole Robinson 已提交
4000
                        unsigned int flags ATTRIBUTE_UNUSED) {
4001 4002 4003
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
C
Cole Robinson 已提交
4004
    int i;
4005
    int ret = -1;
C
Cole Robinson 已提交
4006

4007
    testDriverLock(privconn);
4008 4009
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
4010
    testDriverUnlock(privconn);
4011 4012 4013

    if (privpool == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
4014
        goto cleanup;
4015 4016 4017 4018 4019 4020 4021 4022 4023
    }


    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);
4024
        goto cleanup;
4025 4026 4027 4028 4029
    }

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


C
Cole Robinson 已提交
4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056
    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;
        }
    }
4057
    ret = 0;
C
Cole Robinson 已提交
4058

4059
cleanup:
4060 4061
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4062
    return ret;
C
Cole Robinson 已提交
4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078
}


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
4079
testStorageVolumeGetInfo(virStorageVolPtr vol,
C
Cole Robinson 已提交
4080
                         virStorageVolInfoPtr info) {
4081 4082 4083
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
4084
    int ret = -1;
4085

4086
    testDriverLock(privconn);
4087 4088
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
4089
    testDriverUnlock(privconn);
4090 4091 4092

    if (privpool == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
4093
        goto cleanup;
4094 4095 4096 4097 4098 4099 4100 4101
    }

    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);
4102
        goto cleanup;
4103 4104 4105 4106 4107
    }

    if (!virStoragePoolObjIsActive(privpool)) {
        testError(vol->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is not active"), vol->pool);
4108
        goto cleanup;
4109
    }
C
Cole Robinson 已提交
4110 4111 4112 4113 4114

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

4117
cleanup:
4118 4119
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4120
    return ret;
C
Cole Robinson 已提交
4121 4122 4123
}

static char *
4124
testStorageVolumeGetXMLDesc(virStorageVolPtr vol,
C
Cole Robinson 已提交
4125
                            unsigned int flags ATTRIBUTE_UNUSED) {
4126 4127 4128
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
4129
    char *ret = NULL;
4130

4131
    testDriverLock(privconn);
4132 4133
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
4134
    testDriverUnlock(privconn);
4135 4136 4137

    if (privpool == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
4138
        goto cleanup;
4139 4140 4141 4142 4143 4144 4145 4146
    }

    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);
4147
        goto cleanup;
4148
    }
C
Cole Robinson 已提交
4149

4150 4151 4152
    if (!virStoragePoolObjIsActive(privpool)) {
        testError(vol->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is not active"), vol->pool);
4153
        goto cleanup;
4154 4155
    }

4156 4157 4158
    ret = virStorageVolDefFormat(vol->conn, privpool->def, privvol);

cleanup:
4159 4160
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4161
    return ret;
C
Cole Robinson 已提交
4162 4163 4164
}

static char *
4165 4166 4167 4168
testStorageVolumeGetPath(virStorageVolPtr vol) {
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
4169
    char *ret = NULL;
4170

4171
    testDriverLock(privconn);
4172 4173
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
4174
    testDriverUnlock(privconn);
4175 4176 4177

    if (privpool == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
4178
        goto cleanup;
4179 4180 4181 4182 4183 4184 4185 4186
    }

    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);
4187
        goto cleanup;
4188 4189 4190 4191 4192
    }

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

C
Cole Robinson 已提交
4196
    ret = strdup(privvol->target.path);
4197
    if (ret == NULL)
4198
        virReportOOMError(vol->conn);
4199 4200

cleanup:
4201 4202
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4203 4204 4205
    return ret;
}

4206

4207
/* Node device implementations */
4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222
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;
}

4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360
static int
testNodeNumOfDevices(virConnectPtr conn,
                     const char *cap,
                     unsigned int flags ATTRIBUTE_UNUSED)
{
    testConnPtr driver = conn->privateData;
    int ndevs = 0;
    unsigned int i;

    testDriverLock(driver);
    for (i = 0; i < driver->devs.count; i++)
        if ((cap == NULL) ||
            virNodeDeviceHasCap(driver->devs.objs[i], cap))
            ++ndevs;
    testDriverUnlock(driver);

    return ndevs;
}

static int
testNodeListDevices(virConnectPtr conn,
                    const char *cap,
                    char **const names,
                    int maxnames,
                    unsigned int flags ATTRIBUTE_UNUSED)
{
    testConnPtr driver = conn->privateData;
    int ndevs = 0;
    unsigned int i;

    testDriverLock(driver);
    for (i = 0; i < driver->devs.count && ndevs < maxnames; i++) {
        virNodeDeviceObjLock(driver->devs.objs[i]);
        if (cap == NULL ||
            virNodeDeviceHasCap(driver->devs.objs[i], cap)) {
            if ((names[ndevs++] = strdup(driver->devs.objs[i]->def->name)) == NULL) {
                virNodeDeviceObjUnlock(driver->devs.objs[i]);
                goto failure;
            }
        }
        virNodeDeviceObjUnlock(driver->devs.objs[i]);
    }
    testDriverUnlock(driver);

    return ndevs;

 failure:
    testDriverUnlock(driver);
    --ndevs;
    while (--ndevs >= 0)
        VIR_FREE(names[ndevs]);
    return -1;
}

static virNodeDevicePtr
testNodeDeviceLookupByName(virConnectPtr conn, const char *name)
{
    testConnPtr driver = conn->privateData;
    virNodeDeviceObjPtr obj;
    virNodeDevicePtr ret = NULL;

    testDriverLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, name);
    testDriverUnlock(driver);

    if (!obj) {
        virNodeDeviceReportError(conn, VIR_ERR_NO_NODE_DEVICE, NULL);
        goto cleanup;
    }

    ret = virGetNodeDevice(conn, name);

cleanup:
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

static char *
testNodeDeviceDumpXML(virNodeDevicePtr dev,
                      unsigned int flags ATTRIBUTE_UNUSED)
{
    testConnPtr driver = dev->conn->privateData;
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

    testDriverLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
    testDriverUnlock(driver);

    if (!obj) {
        virNodeDeviceReportError(dev->conn, VIR_ERR_NO_NODE_DEVICE,
                                _("no node device with matching name '%s'"),
                                 dev->name);
        goto cleanup;
    }

    ret = virNodeDeviceDefFormat(dev->conn, obj->def);

cleanup:
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

static char *
testNodeDeviceGetParent(virNodeDevicePtr dev)
{
    testConnPtr driver = dev->conn->privateData;
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

    testDriverLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
    testDriverUnlock(driver);

    if (!obj) {
        virNodeDeviceReportError(dev->conn, VIR_ERR_NO_NODE_DEVICE,
                                _("no node device with matching name '%s'"),
                                 dev->name);
        goto cleanup;
    }

    if (obj->def->parent) {
        ret = strdup(obj->def->parent);
        if (!ret)
            virReportOOMError(dev->conn);
    } else {
        virNodeDeviceReportError(dev->conn, VIR_ERR_INTERNAL_ERROR,
                                 "%s", _("no parent for this device"));
    }

cleanup:
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

4361

4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430
static int
testNodeDeviceNumOfCaps(virNodeDevicePtr dev)
{
    testConnPtr driver = dev->conn->privateData;
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

    testDriverLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
    testDriverUnlock(driver);

    if (!obj) {
        virNodeDeviceReportError(dev->conn, VIR_ERR_NO_NODE_DEVICE,
                                _("no node device with matching name '%s'"),
                                 dev->name);
        goto cleanup;
    }

    for (caps = obj->def->caps; caps; caps = caps->next)
        ++ncaps;
    ret = ncaps;

cleanup:
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}


static int
testNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
    testConnPtr driver = dev->conn->privateData;
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

    testDriverLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
    testDriverUnlock(driver);

    if (!obj) {
        virNodeDeviceReportError(dev->conn, VIR_ERR_NO_NODE_DEVICE,
                                _("no node device with matching name '%s'"),
                                 dev->name);
        goto cleanup;
    }

    for (caps = obj->def->caps; caps && ncaps < maxnames; caps = caps->next) {
        names[ncaps] = strdup(virNodeDevCapTypeToString(caps->type));
        if (names[ncaps++] == NULL)
            goto cleanup;
    }
    ret = ncaps;

cleanup:
    if (obj)
        virNodeDeviceObjUnlock(obj);
    if (ret == -1) {
        --ncaps;
        while (--ncaps >= 0)
            VIR_FREE(names[ncaps]);
    }
    return ret;
}

4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555
static virNodeDevicePtr
testNodeDeviceCreateXML(virConnectPtr conn,
                        const char *xmlDesc,
                        unsigned int flags ATTRIBUTE_UNUSED)
{
    testConnPtr driver = conn->privateData;
    virNodeDeviceDefPtr def = NULL;
    virNodeDeviceObjPtr obj = NULL;
    char *wwnn = NULL, *wwpn = NULL;
    int parent_host = -1;
    virNodeDevicePtr dev = NULL;
    virNodeDevCapsDefPtr caps;

    testDriverLock(driver);

    def = virNodeDeviceDefParseString(conn, xmlDesc, CREATE_DEVICE);
    if (def == NULL) {
        goto cleanup;
    }

    /* We run these next two simply for validation */
    if (virNodeDeviceGetWWNs(conn, def, &wwnn, &wwpn) == -1) {
        goto cleanup;
    }

    if (virNodeDeviceGetParentHost(conn,
                                   &driver->devs,
                                   def->name,
                                   def->parent,
                                   &parent_host) == -1) {
        goto cleanup;
    }

    /* 'name' is supposed to be filled in by the node device backend, which
     * we don't have. Use WWPN instead. */
    VIR_FREE(def->name);
    if (!(def->name = strdup(wwpn))) {
        virReportOOMError(conn);
        goto cleanup;
    }

    /* Fill in a random 'host' value, since this would also come from
     * the backend */
    caps = def->caps;
    while (caps) {
        if (caps->type != VIR_NODE_DEV_CAP_SCSI_HOST)
            continue;

        caps->data.scsi_host.host = virRandom(1024);
        caps = caps->next;
    }


    if (!(obj = virNodeDeviceAssignDef(conn, &driver->devs, def))) {
        goto cleanup;
    }
    virNodeDeviceObjUnlock(obj);

    dev = virGetNodeDevice(conn, def->name);
    def = NULL;
cleanup:
    testDriverUnlock(driver);
    if (def)
        virNodeDeviceDefFree(def);
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return dev;
}

static int
testNodeDeviceDestroy(virNodeDevicePtr dev)
{
    int ret = 0;
    testConnPtr driver = dev->conn->privateData;
    virNodeDeviceObjPtr obj = NULL;
    char *parent_name = NULL, *wwnn = NULL, *wwpn = NULL;
    int parent_host = -1;

    testDriverLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
    testDriverUnlock(driver);

    if (!obj) {
        virNodeDeviceReportError(dev->conn, VIR_ERR_NO_NODE_DEVICE, NULL);
        goto out;
    }

    if (virNodeDeviceGetWWNs(dev->conn, obj->def, &wwnn, &wwpn) == -1) {
        goto out;
    }

    parent_name = strdup(obj->def->parent);
    if (parent_name == NULL) {
        virReportOOMError(dev->conn);
        goto out;
    }

    /* virNodeDeviceGetParentHost will cause the device object's lock to be
     * taken, so we have to dup the parent's name and drop the lock
     * before calling it.  We don't need the reference to the object
     * any more once we have the parent's name.  */
    virNodeDeviceObjUnlock(obj);

    /* We do this just for basic validation */
    if (virNodeDeviceGetParentHost(dev->conn,
                                   &driver->devs,
                                   dev->name,
                                   parent_name,
                                   &parent_host) == -1) {
        obj = NULL;
        goto out;
    }

    virNodeDeviceObjLock(obj);
    virNodeDeviceObjRemove(&driver->devs, obj);

out:
    if (obj)
        virNodeDeviceObjUnlock(obj);
    VIR_FREE(parent_name);
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return ret;
}

4556 4557

/* Domain event implementations */
4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653
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);
}

4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667
static virDrvOpenStatus testSecretOpen(virConnectPtr conn,
                                       virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                       int flags ATTRIBUTE_UNUSED) {
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

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

static int testSecretClose(virConnectPtr conn) {
    conn->secretPrivateData = NULL;
    return 0;
}
4668

4669 4670 4671 4672 4673
static virDriver testDriver = {
    VIR_DRV_TEST,
    "Test",
    testOpen, /* open */
    testClose, /* close */
4674
    NULL, /* supports_feature */
4675 4676
    NULL, /* type */
    testGetVersion, /* version */
4677
    testGetHostname, /* getHostname */
4678 4679 4680 4681 4682
    testGetMaxVCPUs, /* getMaxVcpus */
    testNodeGetInfo, /* nodeGetInfo */
    testGetCapabilities, /* getCapabilities */
    testListDomains, /* listDomains */
    testNumOfDomains, /* numOfDomains */
4683
    testDomainCreateXML, /* domainCreateXML */
4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703
    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 */
4704 4705
    NULL, /* domainGetSecurityLabel */
    NULL, /* nodeGetSecurityModel */
4706
    testDomainDumpXML, /* domainDumpXML */
4707 4708
    NULL, /* domainXMLFromNative */
    NULL, /* domainXMLToNative */
4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720
    testListDefinedDomains, /* listDefinedDomains */
    testNumOfDefinedDomains, /* numOfDefinedDomains */
    testDomainCreate, /* domainCreate */
    testDomainDefineXML, /* domainDefineXML */
    testDomainUndefine, /* domainUndefine */
    NULL, /* domainAttachDevice */
    NULL, /* domainDetachDevice */
    testDomainGetAutostart, /* domainGetAutostart */
    testDomainSetAutostart, /* domainSetAutostart */
    testDomainGetSchedulerType, /* domainGetSchedulerType */
    testDomainGetSchedulerParams, /* domainGetSchedulerParameters */
    testDomainSetSchedulerParams, /* domainSetSchedulerParameters */
4721 4722 4723
    NULL, /* domainMigratePrepare */
    NULL, /* domainMigratePerform */
    NULL, /* domainMigrateFinish */
4724 4725
    testDomainBlockStats, /* domainBlockStats */
    testDomainInterfaceStats, /* domainInterfaceStats */
R
Richard W.M. Jones 已提交
4726
    NULL, /* domainBlockPeek */
R
Richard W.M. Jones 已提交
4727
    NULL, /* domainMemoryPeek */
4728
    testNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
4729
    NULL, /* getFreeMemory */
4730 4731
    testDomainEventRegister, /* domainEventRegister */
    testDomainEventDeregister, /* domainEventDeregister */
D
Daniel Veillard 已提交
4732 4733
    NULL, /* domainMigratePrepare2 */
    NULL, /* domainMigrateFinish2 */
4734
    NULL, /* nodeDeviceDettach */
4735 4736
    NULL, /* nodeDeviceReAttach */
    NULL, /* nodeDeviceReset */
C
Chris Lalancette 已提交
4737
    NULL, /* domainMigratePrepareTunnel */
4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760
};

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

L
Laine Stump 已提交
4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778
static virInterfaceDriver testInterfaceDriver = {
    "Test",                     /* name */
    testOpenInterface,          /* open */
    testCloseInterface,         /* close */
    testNumOfInterfaces,        /* numOfInterfaces */
    testListInterfaces,         /* listInterfaces */
    testNumOfDefinedInterfaces, /* numOfDefinedInterfaces */
    testListDefinedInterfaces,  /* listDefinedInterfaces */
    testLookupInterfaceByName,  /* interfaceLookupByName */
    testLookupInterfaceByMACString, /* interfaceLookupByMACString */
    testInterfaceGetXMLDesc,    /* interfaceGetXMLDesc */
    testInterfaceDefineXML,     /* interfaceDefineXML */
    testInterfaceUndefine,      /* interfaceUndefine */
    testInterfaceCreate,        /* interfaceCreate */
    testInterfaceDestroy,       /* interfaceDestroy */
};


4779 4780 4781 4782
static virStorageDriver testStorageDriver = {
    .name = "Test",
    .open = testStorageOpen,
    .close = testStorageClose,
C
Cole Robinson 已提交
4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810

    .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,
4811
    .volCreateXMLFrom = testStorageVolumeCreateXMLFrom,
C
Cole Robinson 已提交
4812 4813 4814 4815
    .volDelete = testStorageVolumeDelete,
    .volGetInfo = testStorageVolumeGetInfo,
    .volGetXMLDesc = testStorageVolumeGetXMLDesc,
    .volGetPath = testStorageVolumeGetPath,
4816 4817
};

4818 4819 4820 4821
static virDeviceMonitor testDevMonitor = {
    .name = "Test",
    .open = testDevMonOpen,
    .close = testDevMonClose,
4822 4823 4824 4825 4826 4827 4828 4829

    .numOfDevices = testNodeNumOfDevices,
    .listDevices = testNodeListDevices,
    .deviceLookupByName = testNodeDeviceLookupByName,
    .deviceDumpXML = testNodeDeviceDumpXML,
    .deviceGetParent = testNodeDeviceGetParent,
    .deviceNumOfCaps = testNodeDeviceNumOfCaps,
    .deviceListCaps = testNodeDeviceListCaps,
4830 4831
    .deviceCreateXML = testNodeDeviceCreateXML,
    .deviceDestroy = testNodeDeviceDestroy,
4832 4833
};

4834 4835 4836 4837 4838
static virSecretDriver testSecretDriver = {
    .name = "Test",
    .open = testSecretOpen,
    .close = testSecretClose,
};
4839 4840


4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
    if (virRegisterDriver(&testDriver) < 0)
        return -1;
    if (virRegisterNetworkDriver(&testNetworkDriver) < 0)
        return -1;
L
Laine Stump 已提交
4853 4854
    if (virRegisterInterfaceDriver(&testInterfaceDriver) < 0)
        return -1;
4855 4856
    if (virRegisterStorageDriver(&testStorageDriver) < 0)
        return -1;
4857 4858
    if (virRegisterDeviceMonitor(&testDevMonitor) < 0)
        return -1;
4859 4860
    if (virRegisterSecretDriver(&testSecretDriver) < 0)
        return -1;
4861

4862 4863
    return 0;
}