test_driver.c 137.4 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
    memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));
365

366 367 368 369 370 371 372 373 374 375
    // 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;
    }

376 377 378 379 380
    if (!(privconn->caps = testBuildCapabilities(conn)))
        goto error;

    privconn->nextDomID = 1;

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

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

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

414
    if (!(pooldef = virStoragePoolDefParseString(conn, defaultPoolXML)))
C
Cole Robinson 已提交
415 416 417 418 419 420 421
        goto error;

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

423
    if (testStoragePoolObjSetDefaults(conn, poolobj) == -1) {
424
        virStoragePoolObjUnlock(poolobj);
C
Cole Robinson 已提交
425
        goto error;
426
    }
C
Cole Robinson 已提交
427
    poolobj->active = 1;
428
    virStoragePoolObjUnlock(poolobj);
C
Cole Robinson 已提交
429

430 431 432 433 434 435 436 437 438 439
    /* 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);

440
    testDriverUnlock(privconn);
441

442 443 444
    return VIR_DRV_OPEN_SUCCESS;

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


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

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

485 486 487 488 489 490 491 492 493
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;
494
    virStorageVolDefPtr def = NULL;
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 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

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

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

592
    testDriverLock(privconn);
593
    conn->privateData = privconn;
594 595 596

    if (!(privconn->caps = testBuildCapabilities(conn)))
        goto error;
597 598

    if ((fd = open(file, O_RDONLY)) < 0) {
599 600 601
        virReportSystemError(NULL, errno,
                             _("loading host definition file '%s'"),
                             file);
602
        goto error;
603 604
    }

605 606 607
    if (!(xml = xmlReadFd(fd, file, NULL,
                          XML_PARSE_NOENT | XML_PARSE_NONET |
                          XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
608 609
        testError(NULL, VIR_ERR_INTERNAL_ERROR,
                  _("Invalid XML in file '%s'"), file);
610
        goto error;
611
    }
612 613
    close(fd);
    fd = -1;
614

615 616
    root = xmlDocGetRootElement(xml);
    if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "node"))) {
617 618
        testError(NULL, VIR_ERR_XML_ERROR, "%s",
                  _("Root element is not 'node'"));
619
        goto error;
620 621
    }

622 623
    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
C
Cole Robinson 已提交
624 625
        testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s",
                  _("creating xpath context"));
626
        goto error;
627
    }
628

629
    privconn->nextDomID = 1;
630
    privconn->numCells = 0;
C
Chris Lalancette 已提交
631 632 633 634 635
    if (virStrcpyStatic(privconn->path, file) == NULL) {
        testError(NULL, VIR_ERR_INTERNAL_ERROR,
                  _("Path %s too big for destination"), file);
        goto error;
    }
636 637 638
    memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));

    nodeInfo = &privconn->nodeInfo;
639
    ret = virXPathLong(conn, "string(/node/cpu/nodes[1])", ctxt, &l);
640 641 642
    if (ret == 0) {
        nodeInfo->nodes = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
643
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu numa nodes"));
644
        goto error;
645
    }
646

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

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

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

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

689
    str = virXPathString(conn, "string(/node/cpu/model[1])", ctxt);
690
    if (str != NULL) {
C
Chris Lalancette 已提交
691 692 693 694 695 696
        if (virStrcpyStatic(nodeInfo->model, str) == NULL) {
            testError(NULL, VIR_ERR_INTERNAL_ERROR,
                      _("Model %s too big for destination"), str);
            VIR_FREE(str);
            goto error;
        }
697
        VIR_FREE(str);
698 699
    }

700
    ret = virXPathLong(conn, "string(/node/memory[1])", ctxt, &l);
701 702 703
    if (ret == 0) {
        nodeInfo->memory = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
704
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node memory"));
705
        goto error;
706
    }
707

708
    ret = virXPathNodeSet(conn, "/node/domain", ctxt, &domains);
709
    if (ret < 0) {
J
Jim Meyering 已提交
710
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node domain list"));
711
        goto error;
712
    }
713

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

735 736
        if (testDomainGenerateIfnames(conn, def) < 0 ||
            !(dom = virDomainAssignDef(conn, &privconn->domains, def))) {
737
            virDomainDefFree(def);
738 739
            goto error;
        }
740 741 742 743

        dom->state = VIR_DOMAIN_RUNNING;
        dom->def->id = privconn->nextDomID++;
        dom->persistent = 1;
744
        virDomainObjUnlock(dom);
745
    }
746
    VIR_FREE(domains);
747

748
    ret = virXPathNodeSet(conn, "/node/network", ctxt, &networks);
749
    if (ret < 0) {
J
Jim Meyering 已提交
750
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node network list"));
751 752 753 754 755 756 757 758
        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);
759
            if (!absFile) {
J
Jim Meyering 已提交
760
                testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("resolving network filename"));
761 762
                goto error;
            }
763 764

            def = virNetworkDefParseFile(conn, absFile);
765
            VIR_FREE(absFile);
766 767 768 769 770
            if (!def)
                goto error;
        } else {
            if ((def = virNetworkDefParseNode(conn, xml, networks[i])) == NULL)
                goto error;
771
        }
772 773 774 775
        if (!(net = virNetworkAssignDef(conn, &privconn->networks,
                                        def))) {
            virNetworkDefFree(def);
            goto error;
776
        }
777
        net->persistent = 1;
778
        net->active = 1;
779
        virNetworkObjUnlock(net);
780
    }
781
    VIR_FREE(networks);
782

L
Laine Stump 已提交
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804
    /* 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 {
805
            if ((def = virInterfaceDefParseNode(conn, xml, ifaces[i])) == NULL)
L
Laine Stump 已提交
806 807
                goto error;
        }
808

L
Laine Stump 已提交
809 810 811 812
        if (!(iface = virInterfaceAssignDef(conn, &privconn->ifaces, def))) {
            virInterfaceDefFree(def);
            goto error;
        }
813 814

        iface->active = 1;
L
Laine Stump 已提交
815 816 817 818
        virInterfaceObjUnlock(iface);
    }
    VIR_FREE(ifaces);

C
Cole Robinson 已提交
819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837
    /* 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;
            }

838
            def = virStoragePoolDefParseFile(conn, absFile);
C
Cole Robinson 已提交
839 840 841 842
            VIR_FREE(absFile);
            if (!def)
                goto error;
        } else {
843 844
            if ((def = virStoragePoolDefParseNode(conn, xml,
                                                  pools[i])) == NULL) {
C
Cole Robinson 已提交
845 846 847 848 849 850 851 852 853 854
                goto error;
            }
        }

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

855
        if (testStoragePoolObjSetDefaults(conn, pool) == -1) {
856
            virStoragePoolObjUnlock(pool);
C
Cole Robinson 已提交
857
            goto error;
858
        }
C
Cole Robinson 已提交
859
        pool->active = 1;
860 861 862 863 864 865 866

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

867
        virStoragePoolObjUnlock(pool);
C
Cole Robinson 已提交
868
    }
869
    VIR_FREE(pools);
C
Cole Robinson 已提交
870

871 872 873 874 875 876 877 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
    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 已提交
908
    xmlXPathFreeContext(ctxt);
909
    xmlFreeDoc(xml);
910
    testDriverUnlock(privconn);
911

912
    return (0);
913 914

 error:
J
Jim Meyering 已提交
915
    xmlXPathFreeContext(ctxt);
916
    xmlFreeDoc(xml);
917 918
    VIR_FREE(domains);
    VIR_FREE(networks);
L
Laine Stump 已提交
919
    VIR_FREE(ifaces);
C
Cole Robinson 已提交
920
    VIR_FREE(pools);
921 922
    if (fd != -1)
        close(fd);
923
    virDomainObjListFree(&privconn->domains);
924
    virNetworkObjListFree(&privconn->networks);
L
Laine Stump 已提交
925
    virInterfaceObjListFree(&privconn->ifaces);
C
Cole Robinson 已提交
926
    virStoragePoolObjListFree(&privconn->pools);
927
    testDriverUnlock(privconn);
928
    VIR_FREE(privconn);
929
    conn->privateData = NULL;
930
    return VIR_DRV_OPEN_ERROR;
931 932
}

933

934
static virDrvOpenStatus testOpen(virConnectPtr conn,
935
                    virConnectAuthPtr auth ATTRIBUTE_UNUSED,
936
                    int flags ATTRIBUTE_UNUSED)
937
{
938
    int ret;
939

940
    if (!conn->uri)
941
        return VIR_DRV_OPEN_DECLINED;
942

943
    if (!conn->uri->scheme || STRNEQ(conn->uri->scheme, "test"))
944
        return VIR_DRV_OPEN_DECLINED;
945

946
    /* Remote driver should handle these. */
947
    if (conn->uri->server)
948 949
        return VIR_DRV_OPEN_DECLINED;

950
    /* From this point on, the connection is for us. */
951 952 953
    if (!conn->uri->path
        || conn->uri->path[0] == '\0'
        || (conn->uri->path[0] == '/' && conn->uri->path[1] == '\0')) {
954
        testError (NULL, VIR_ERR_INVALID_ARG,
J
Jim Meyering 已提交
955
                   "%s", _("testOpen: supply a path or use test:///default"));
956 957
        return VIR_DRV_OPEN_ERROR;
    }
958

959
    if (STREQ(conn->uri->path, "/default"))
960 961
        ret = testOpenDefault(conn);
    else
962
        ret = testOpenFromFile(conn,
963
                               conn->uri->path);
964

965 966
    if (ret == VIR_DRV_OPEN_SUCCESS) {
        testConnPtr privconn = conn->privateData;
967
        testDriverLock(privconn);
968 969 970 971
        /* Init callback list */
        if (VIR_ALLOC(privconn->domainEventCallbacks) < 0 ||
            !(privconn->domainEventQueue = virDomainEventQueueNew())) {
            virReportOOMError(NULL);
972
            testDriverUnlock(privconn);
973 974 975 976 977 978 979 980
            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.");
981
        testDriverUnlock(privconn);
982 983
    }

984
    return (ret);
985 986
}

987
static int testClose(virConnectPtr conn)
988
{
989
    testConnPtr privconn = conn->privateData;
990
    testDriverLock(privconn);
991
    virCapabilitiesFree(privconn->caps);
992
    virDomainObjListFree(&privconn->domains);
993
    virNetworkObjListFree(&privconn->networks);
L
Laine Stump 已提交
994
    virInterfaceObjListFree(&privconn->ifaces);
C
Cole Robinson 已提交
995
    virStoragePoolObjListFree(&privconn->pools);
996 997 998 999 1000 1001 1002

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

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

1003
    testDriverUnlock(privconn);
1004
    virMutexDestroy(&privconn->lock);
1005

1006
    VIR_FREE (privconn);
1007
    conn->privateData = NULL;
1008
    return 0;
1009 1010
}

1011 1012
static int testGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
                          unsigned long *hvVer)
1013
{
1014 1015
    *hvVer = 2;
    return (0);
1016 1017
}

1018
static char *testGetHostname (virConnectPtr conn)
1019
{
1020
    char *result;
1021

1022 1023
    result = virGetHostname();
    if (result == NULL) {
1024 1025
        virReportSystemError(conn, errno,
                             "%s", _("cannot lookup hostname"));
1026 1027
        return NULL;
    }
1028 1029
    /* Caller frees this string. */
    return result;
1030 1031
}

1032 1033 1034 1035 1036 1037 1038 1039
static int testGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED,
                           const char *type ATTRIBUTE_UNUSED)
{
    return 32;
}

static int testNodeGetInfo(virConnectPtr conn,
                           virNodeInfoPtr info)
1040
{
1041
    testConnPtr privconn = conn->privateData;
1042
    testDriverLock(privconn);
1043
    memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo));
1044
    testDriverUnlock(privconn);
1045
    return (0);
1046 1047
}

1048
static char *testGetCapabilities (virConnectPtr conn)
1049
{
1050
    testConnPtr privconn = conn->privateData;
1051
    char *xml;
1052
    testDriverLock(privconn);
1053
    if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL)
1054
        virReportOOMError(conn);
1055
    testDriverUnlock(privconn);
1056
    return xml;
1057 1058
}

1059
static int testNumOfDomains(virConnectPtr conn)
1060
{
1061
    testConnPtr privconn = conn->privateData;
1062
    unsigned int numActive = 0, i;
1063

1064
    testDriverLock(privconn);
1065 1066
    for (i = 0 ; i < privconn->domains.count ; i++)
        if (virDomainIsActive(privconn->domains.objs[i]))
1067
            numActive++;
1068
    testDriverUnlock(privconn);
1069

1070
    return numActive;
1071 1072
}

1073
static virDomainPtr
1074
testDomainCreateXML(virConnectPtr conn, const char *xml,
1075
                      unsigned int flags ATTRIBUTE_UNUSED)
1076
{
1077
    testConnPtr privconn = conn->privateData;
1078
    virDomainPtr ret = NULL;
1079
    virDomainDefPtr def;
1080
    virDomainObjPtr dom = NULL;
1081
    virDomainEventPtr event = NULL;
1082

1083
    testDriverLock(privconn);
1084 1085
    if ((def = virDomainDefParseString(conn, privconn->caps, xml,
                                       VIR_DOMAIN_XML_INACTIVE)) == NULL)
1086
        goto cleanup;
1087

1088
    if (testDomainGenerateIfnames(conn, def) < 0)
1089
        goto cleanup;
1090 1091 1092
    if (!(dom = virDomainAssignDef(conn, &privconn->domains, def)))
        goto cleanup;
    def = NULL;
1093 1094
    dom->state = VIR_DOMAIN_RUNNING;
    dom->def->id = privconn->nextDomID++;
1095

1096 1097 1098 1099
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);

1100
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1101
    if (ret)
1102
        ret->id = dom->def->id;
1103 1104

cleanup:
1105 1106
    if (dom)
        virDomainObjUnlock(dom);
1107 1108
    if (event)
        testDomainEventQueue(privconn, event);
1109 1110
    if (def)
        virDomainDefFree(def);
1111
    testDriverUnlock(privconn);
1112
    return ret;
1113 1114 1115
}


1116 1117
static virDomainPtr testLookupDomainByID(virConnectPtr conn,
                                         int id)
1118
{
1119
    testConnPtr privconn = conn->privateData;
1120 1121
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1122

1123 1124 1125 1126 1127
    testDriverLock(privconn);
    dom = virDomainFindByID(&privconn->domains, id);
    testDriverUnlock(privconn);

    if (dom == NULL) {
1128
        testError (conn, VIR_ERR_NO_DOMAIN, NULL);
1129
        goto cleanup;
1130 1131
    }

1132
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1133 1134 1135 1136
    if (ret)
        ret->id = dom->def->id;

cleanup:
1137 1138
    if (dom)
        virDomainObjUnlock(dom);
1139
    return ret;
1140 1141
}

1142 1143
static virDomainPtr testLookupDomainByUUID(virConnectPtr conn,
                                           const unsigned char *uuid)
1144
{
1145
    testConnPtr privconn = conn->privateData;
1146 1147
    virDomainPtr ret = NULL;
    virDomainObjPtr dom ;
1148

1149 1150 1151 1152 1153
    testDriverLock(privconn);
    dom = virDomainFindByUUID(&privconn->domains, uuid);
    testDriverUnlock(privconn);

    if (dom == NULL) {
1154
        testError (conn, VIR_ERR_NO_DOMAIN, NULL);
1155
        goto cleanup;
1156
    }
1157

1158
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1159 1160 1161 1162
    if (ret)
        ret->id = dom->def->id;

cleanup:
1163 1164
    if (dom)
        virDomainObjUnlock(dom);
1165
    return ret;
1166 1167
}

1168 1169
static virDomainPtr testLookupDomainByName(virConnectPtr conn,
                                           const char *name)
1170
{
1171
    testConnPtr privconn = conn->privateData;
1172 1173
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1174

1175 1176 1177 1178 1179
    testDriverLock(privconn);
    dom = virDomainFindByName(&privconn->domains, name);
    testDriverUnlock(privconn);

    if (dom == NULL) {
1180
        testError (conn, VIR_ERR_NO_DOMAIN, NULL);
1181
        goto cleanup;
1182
    }
1183

1184
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1185 1186 1187 1188
    if (ret)
        ret->id = dom->def->id;

cleanup:
1189 1190
    if (dom)
        virDomainObjUnlock(dom);
1191
    return ret;
1192 1193
}

1194 1195 1196
static int testListDomains (virConnectPtr conn,
                            int *ids,
                            int maxids)
1197
{
1198
    testConnPtr privconn = conn->privateData;
1199
    unsigned int n = 0, i;
1200

1201 1202 1203
    testDriverLock(privconn);
    for (i = 0 ; i < privconn->domains.count && n < maxids ; i++) {
        virDomainObjLock(privconn->domains.objs[i]);
1204 1205
        if (virDomainIsActive(privconn->domains.objs[i]))
            ids[n++] = privconn->domains.objs[i]->def->id;
1206 1207 1208
        virDomainObjUnlock(privconn->domains.objs[i]);
    }
    testDriverUnlock(privconn);
1209

1210
    return n;
1211 1212
}

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

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

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

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

1241

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

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

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

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

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

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

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

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

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

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

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

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

cleanup:
1325 1326
    if (privdom)
        virDomainObjUnlock(privdom);
1327 1328 1329 1330 1331 1332

    if (event) {
        testDriverLock(privconn);
        testDomainEventQueue(privconn, event);
        testDriverUnlock(privconn);
    }
1333
    return ret;
1334 1335
}

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

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

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

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

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

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

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

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

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

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

1406 1407
    case VIR_DOMAIN_LIFECYCLE_RESTART:
        privdom->state = VIR_DOMAIN_RUNNING;
1408 1409
        break;

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

1416 1417
    case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME:
        privdom->state = VIR_DOMAIN_RUNNING;
1418
        break;
1419

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

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

1438 1439 1440
    ret = 0;

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

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

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

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

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

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

cleanup:
1481 1482
    if (privdom)
        virDomainObjUnlock(privdom);
1483
    return ret;
1484 1485
}

1486 1487 1488 1489 1490
#define TEST_SAVE_MAGIC "TestGuestMagic"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1677
    testDriverLock(privconn);
1678 1679 1680 1681 1682
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1683
        goto cleanup;
1684
    }
1685 1686

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

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

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

static unsigned long testGetMaxMemory(virDomainPtr domain) {
1734 1735
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1736
    unsigned long ret = 0;
1737

1738
    testDriverLock(privconn);
1739 1740
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1741
    testDriverUnlock(privconn);
1742 1743 1744

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1745
        goto cleanup;
1746
    }
1747

1748 1749 1750
    ret = privdom->def->maxmem;

cleanup:
1751 1752
    if (privdom)
        virDomainObjUnlock(privdom);
1753
    return ret;
1754 1755 1756 1757 1758
}

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

1763
    testDriverLock(privconn);
1764 1765
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1766
    testDriverUnlock(privconn);
1767 1768 1769

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1770
        goto cleanup;
1771
    }
1772 1773

    /* XXX validate not over host memory wrt to other domains */
1774
    privdom->def->maxmem = memory;
1775 1776 1777
    ret = 0;

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

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

1790
    testDriverLock(privconn);
1791 1792
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1793
    testDriverUnlock(privconn);
1794 1795 1796

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1797
        goto cleanup;
1798
    }
1799

1800
    if (memory > privdom->def->maxmem) {
1801
        testError(domain->conn,
1802
                  VIR_ERR_INVALID_ARG, __FUNCTION__);
1803
        goto cleanup;
1804
    }
1805

1806
    privdom->def->memory = memory;
1807 1808 1809
    ret = 0;

cleanup:
1810 1811
    if (privdom)
        virDomainObjUnlock(privdom);
1812
    return ret;
1813 1814 1815 1816
}

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

1821 1822 1823 1824 1825 1826
    testDriverLock(privconn);
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
    testDriverUnlock(privconn);

    if (privdom == NULL) {
1827
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1828
        goto cleanup;
1829
    }
1830

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

1837
    privdom->def->vcpus = nrCpus;
1838 1839 1840
    ret = 0;

cleanup:
1841 1842
    if (privdom)
        virDomainObjUnlock(privdom);
1843
    return ret;
1844 1845
}

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

1853 1854 1855 1856 1857 1858
    testDriverLock(privconn);
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
    testDriverUnlock(privconn);

    if (privdom == NULL) {
1859
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1860
        goto cleanup;
1861
    }
1862

1863 1864
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
1865

1866 1867 1868 1869 1870
    ret = virDomainDefFormat(domain->conn,
                             def,
                             flags);

cleanup:
1871 1872
    if (privdom)
        virDomainObjUnlock(privdom);
1873
    return ret;
1874
}
1875

1876
static int testNumOfDefinedDomains(virConnectPtr conn) {
1877
    testConnPtr privconn = conn->privateData;
1878
    unsigned int numInactive = 0, i;
1879

1880 1881 1882
    testDriverLock(privconn);
    for (i = 0 ; i < privconn->domains.count ; i++) {
        virDomainObjLock(privconn->domains.objs[i]);
1883
        if (!virDomainIsActive(privconn->domains.objs[i]))
1884
            numInactive++;
1885 1886 1887
        virDomainObjUnlock(privconn->domains.objs[i]);
    }
    testDriverUnlock(privconn);
1888

1889
    return numInactive;
1890 1891
}

1892 1893 1894
static int testListDefinedDomains(virConnectPtr conn,
                                  char **const names,
                                  int maxnames) {
1895
    testConnPtr privconn = conn->privateData;
1896
    unsigned int n = 0, i;
1897

1898
    testDriverLock(privconn);
1899
    memset(names, 0, sizeof(*names)*maxnames);
1900 1901
    for (i = 0 ; i < privconn->domains.count && n < maxnames ; i++) {
        virDomainObjLock(privconn->domains.objs[i]);
1902
        if (!virDomainIsActive(privconn->domains.objs[i]) &&
1903 1904
            !(names[n++] = strdup(privconn->domains.objs[i]->def->name))) {
            virDomainObjUnlock(privconn->domains.objs[i]);
1905
            goto no_memory;
1906 1907 1908 1909
        }
        virDomainObjUnlock(privconn->domains.objs[i]);
    }
    testDriverUnlock(privconn);
1910

1911 1912 1913
    return n;

no_memory:
1914
    virReportOOMError(conn);
1915 1916
    for (n = 0 ; n < maxnames ; n++)
        VIR_FREE(names[n]);
1917
    testDriverUnlock(privconn);
1918
    return -1;
1919 1920
}

1921
static virDomainPtr testDomainDefineXML(virConnectPtr conn,
1922
                                        const char *xml) {
1923
    testConnPtr privconn = conn->privateData;
1924
    virDomainPtr ret = NULL;
1925
    virDomainDefPtr def;
1926
    virDomainObjPtr dom = NULL;
1927
    virDomainEventPtr event = NULL;
1928

1929
    testDriverLock(privconn);
1930 1931
    if ((def = virDomainDefParseString(conn, privconn->caps, xml,
                                       VIR_DOMAIN_XML_INACTIVE)) == NULL)
1932
        goto cleanup;
1933

1934 1935 1936
    if (testDomainGenerateIfnames(conn, def) < 0)
        goto cleanup;
    if (!(dom = virDomainAssignDef(conn, &privconn->domains, def)))
1937
        goto cleanup;
1938
    def = NULL;
1939
    dom->persistent = 1;
1940

1941 1942 1943
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_DEFINED,
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED);
1944

1945
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1946
    if (ret)
1947
        ret->id = dom->def->id;
1948 1949 1950

cleanup:
    virDomainDefFree(def);
1951 1952
    if (dom)
        virDomainObjUnlock(dom);
1953 1954
    if (event)
        testDomainEventQueue(privconn, event);
1955
    testDriverUnlock(privconn);
1956
    return ret;
1957 1958
}

1959 1960 1961
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
                                      int startCell, int maxCells) {
1962
    testConnPtr privconn = conn->privateData;
1963
    int i, j;
1964
    int ret = -1;
1965

1966
    testDriverLock(privconn);
1967
    if (startCell > privconn->numCells) {
1968
        testError(conn, VIR_ERR_INVALID_ARG,
J
Jim Meyering 已提交
1969
                  "%s", _("Range exceeds available cells"));
1970
        goto cleanup;
1971 1972 1973 1974 1975 1976 1977
    }

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

1980
cleanup:
1981
    testDriverUnlock(privconn);
1982
    return ret;
1983 1984 1985
}


1986
static int testDomainCreate(virDomainPtr domain) {
1987 1988
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1989
    virDomainEventPtr event = NULL;
1990
    int ret = -1;
1991

1992
    testDriverLock(privconn);
1993 1994 1995 1996 1997
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1998
        goto cleanup;
1999
    }
2000

2001
    if (privdom->state != VIR_DOMAIN_SHUTOFF) {
2002 2003
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Domain '%s' is already running"), domain->name);
2004
        goto cleanup;
2005 2006
    }

2007 2008
    domain->id = privdom->def->id = privconn->nextDomID++;
    privdom->state = VIR_DOMAIN_RUNNING;
2009 2010 2011
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
2012
    ret = 0;
2013

2014
cleanup:
2015 2016
    if (privdom)
        virDomainObjUnlock(privdom);
2017 2018
    if (event)
        testDomainEventQueue(privconn, event);
2019
    testDriverUnlock(privconn);
2020
    return ret;
2021 2022 2023
}

static int testDomainUndefine(virDomainPtr domain) {
2024 2025
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2026
    virDomainEventPtr event = NULL;
2027
    int ret = -1;
2028

2029
    testDriverLock(privconn);
2030 2031 2032 2033 2034
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2035
        goto cleanup;
2036
    }
2037

2038
    if (privdom->state != VIR_DOMAIN_SHUTOFF) {
2039 2040
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Domain '%s' is still running"), domain->name);
2041
        goto cleanup;
2042 2043
    }

2044
    privdom->state = VIR_DOMAIN_SHUTOFF;
2045 2046 2047
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
2048 2049
    virDomainRemoveInactive(&privconn->domains,
                            privdom);
2050
    privdom = NULL;
2051
    ret = 0;
2052

2053
cleanup:
2054 2055
    if (privdom)
        virDomainObjUnlock(privdom);
2056 2057
    if (event)
        testDomainEventQueue(privconn, event);
2058
    testDriverUnlock(privconn);
2059
    return ret;
2060 2061
}

2062 2063 2064
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
2065 2066
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2067
    int ret = -1;
2068

2069
    testDriverLock(privconn);
2070 2071
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
2072
    testDriverUnlock(privconn);
2073 2074 2075

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2076
        goto cleanup;
2077 2078
    }

2079
    *autostart = privdom->autostart;
2080 2081 2082
    ret = 0;

cleanup:
2083 2084
    if (privdom)
        virDomainObjUnlock(privdom);
2085
    return ret;
2086 2087 2088 2089 2090 2091
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
2092 2093
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2094
    int ret = -1;
2095

2096
    testDriverLock(privconn);
2097 2098
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
2099
    testDriverUnlock(privconn);
2100 2101 2102

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2103
        goto cleanup;
2104 2105
    }

2106
    privdom->autostart = autostart ? 1 : 0;
2107 2108 2109
    ret = 0;

cleanup:
2110 2111
    if (privdom)
        virDomainObjUnlock(privdom);
2112
    return ret;
2113
}
2114

2115 2116 2117
static char *testDomainGetSchedulerType(virDomainPtr domain,
                                        int *nparams)
{
2118 2119
    char *type = NULL;

2120 2121
    *nparams = 1;
    type = strdup("fair");
2122
    if (!type)
2123
        virReportOOMError(domain->conn);
2124

2125 2126 2127 2128 2129 2130 2131
    return type;
}

static int testDomainGetSchedulerParams(virDomainPtr domain,
                                        virSchedParameterPtr params,
                                        int *nparams)
{
2132 2133
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2134
    int ret = -1;
2135

2136
    testDriverLock(privconn);
2137 2138
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
2139
    testDriverUnlock(privconn);
2140 2141 2142

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2143
        goto cleanup;
2144 2145
    }

2146
    if (*nparams != 1) {
2147
        testError(domain->conn, VIR_ERR_INVALID_ARG, "nparams");
2148
        goto cleanup;
2149
    }
2150 2151
    strcpy(params[0].field, "weight");
    params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT;
2152 2153 2154
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
    params[0].value.ui = 50;
2155 2156 2157
    ret = 0;

cleanup:
2158 2159
    if (privdom)
        virDomainObjUnlock(privdom);
2160
    return ret;
2161
}
2162 2163


2164 2165 2166 2167
static int testDomainSetSchedulerParams(virDomainPtr domain,
                                        virSchedParameterPtr params,
                                        int nparams)
{
2168 2169
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2170
    int ret = -1;
2171

2172
    testDriverLock(privconn);
2173 2174
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
2175
    testDriverUnlock(privconn);
2176 2177 2178

    if (privdom == NULL) {
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2179
        goto cleanup;
2180 2181
    }

2182
    if (nparams != 1) {
2183
        testError(domain->conn, VIR_ERR_INVALID_ARG, "nparams");
2184
        goto cleanup;
2185
    }
2186
    if (STRNEQ(params[0].field, "weight")) {
2187
        testError(domain->conn, VIR_ERR_INVALID_ARG, "field");
2188
        goto cleanup;
2189 2190
    }
    if (params[0].type != VIR_DOMAIN_SCHED_FIELD_UINT) {
2191
        testError(domain->conn, VIR_ERR_INVALID_ARG, "type");
2192
        goto cleanup;
2193
    }
2194 2195
    /* XXX */
    /*privdom->weight = params[0].value.ui;*/
2196 2197 2198
    ret = 0;

cleanup:
2199 2200
    if (privdom)
        virDomainObjUnlock(privdom);
2201
    return ret;
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 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315
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;
}

2316
static virDrvOpenStatus testOpenNetwork(virConnectPtr conn,
2317
                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334
                                        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)
{
2335 2336
    testConnPtr privconn = conn->privateData;
    virNetworkObjPtr net;
2337
    virNetworkPtr ret = NULL;
2338

2339 2340 2341 2342 2343
    testDriverLock(privconn);
    net = virNetworkFindByUUID(&privconn->networks, uuid);
    testDriverUnlock(privconn);

    if (net == NULL) {
2344
        testError (conn, VIR_ERR_NO_NETWORK, NULL);
2345
        goto cleanup;
2346 2347
    }

2348 2349 2350
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

cleanup:
2351 2352
    if (net)
        virNetworkObjUnlock(net);
2353
    return ret;
2354
}
2355

2356
static virNetworkPtr testLookupNetworkByName(virConnectPtr conn,
2357
                                             const char *name)
2358
{
2359
    testConnPtr privconn = conn->privateData;
2360 2361
    virNetworkObjPtr net;
    virNetworkPtr ret = NULL;
2362

2363 2364 2365 2366 2367
    testDriverLock(privconn);
    net = virNetworkFindByName(&privconn->networks, name);
    testDriverUnlock(privconn);

    if (net == NULL) {
2368
        testError (conn, VIR_ERR_NO_NETWORK, NULL);
2369
        goto cleanup;
2370 2371
    }

2372 2373 2374
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

cleanup:
2375 2376
    if (net)
        virNetworkObjUnlock(net);
2377
    return ret;
2378 2379 2380 2381
}


static int testNumNetworks(virConnectPtr conn) {
2382
    testConnPtr privconn = conn->privateData;
2383
    int numActive = 0, i;
2384

2385 2386 2387
    testDriverLock(privconn);
    for (i = 0 ; i < privconn->networks.count ; i++) {
        virNetworkObjLock(privconn->networks.objs[i]);
2388
        if (virNetworkIsActive(privconn->networks.objs[i]))
2389
            numActive++;
2390 2391 2392
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
2393

2394
    return numActive;
2395 2396 2397
}

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

2401
    testDriverLock(privconn);
2402
    memset(names, 0, sizeof(*names)*nnames);
2403 2404
    for (i = 0 ; i < privconn->networks.count && n < nnames ; i++) {
        virNetworkObjLock(privconn->networks.objs[i]);
2405
        if (virNetworkIsActive(privconn->networks.objs[i]) &&
2406 2407
            !(names[n++] = strdup(privconn->networks.objs[i]->def->name))) {
            virNetworkObjUnlock(privconn->networks.objs[i]);
2408
            goto no_memory;
2409 2410 2411 2412
        }
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
2413

2414 2415 2416
    return n;

no_memory:
2417
    virReportOOMError(conn);
2418 2419
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
2420
    testDriverUnlock(privconn);
2421
    return -1;
2422 2423 2424
}

static int testNumDefinedNetworks(virConnectPtr conn) {
2425
    testConnPtr privconn = conn->privateData;
2426
    int numInactive = 0, i;
2427

2428 2429 2430
    testDriverLock(privconn);
    for (i = 0 ; i < privconn->networks.count ; i++) {
        virNetworkObjLock(privconn->networks.objs[i]);
2431
        if (!virNetworkIsActive(privconn->networks.objs[i]))
2432
            numInactive++;
2433 2434 2435
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
2436

2437
    return numInactive;
2438 2439 2440
}

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

2444
    testDriverLock(privconn);
2445
    memset(names, 0, sizeof(*names)*nnames);
2446 2447
    for (i = 0 ; i < privconn->networks.count && n < nnames ; i++) {
        virNetworkObjLock(privconn->networks.objs[i]);
2448
        if (!virNetworkIsActive(privconn->networks.objs[i]) &&
2449 2450
            !(names[n++] = strdup(privconn->networks.objs[i]->def->name))) {
            virNetworkObjUnlock(privconn->networks.objs[i]);
2451
            goto no_memory;
2452 2453 2454 2455
        }
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
2456

2457 2458 2459
    return n;

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

static virNetworkPtr testNetworkCreate(virConnectPtr conn, const char *xml) {
2468
    testConnPtr privconn = conn->privateData;
2469
    virNetworkDefPtr def;
2470
    virNetworkObjPtr net = NULL;
2471
    virNetworkPtr ret = NULL;
2472

2473
    testDriverLock(privconn);
2474
    if ((def = virNetworkDefParseString(conn, xml)) == NULL)
2475
        goto cleanup;
2476

2477
    if ((net = virNetworkAssignDef(conn, &privconn->networks, def)) == NULL)
2478 2479
        goto cleanup;
    def = NULL;
2480
    net->active = 1;
2481

2482
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
2483

2484 2485
cleanup:
    virNetworkDefFree(def);
2486 2487 2488
    if (net)
        virNetworkObjUnlock(net);
    testDriverUnlock(privconn);
2489
    return ret;
2490 2491 2492
}

static virNetworkPtr testNetworkDefine(virConnectPtr conn, const char *xml) {
2493
    testConnPtr privconn = conn->privateData;
2494
    virNetworkDefPtr def;
2495
    virNetworkObjPtr net = NULL;
2496
    virNetworkPtr ret = NULL;
2497

2498
    testDriverLock(privconn);
2499
    if ((def = virNetworkDefParseString(conn, xml)) == NULL)
2500
        goto cleanup;
2501

2502
    if ((net = virNetworkAssignDef(conn, &privconn->networks, def)) == NULL)
2503 2504
        goto cleanup;
    def = NULL;
2505
    net->persistent = 1;
2506

2507
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
2508 2509 2510

cleanup:
    virNetworkDefFree(def);
2511 2512 2513
    if (net)
        virNetworkObjUnlock(net);
    testDriverUnlock(privconn);
2514
    return ret;
2515 2516 2517
}

static int testNetworkUndefine(virNetworkPtr network) {
2518 2519
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
2520
    int ret = -1;
2521

2522
    testDriverLock(privconn);
2523 2524 2525 2526 2527
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2528
        goto cleanup;
2529
    }
2530

2531
    if (virNetworkIsActive(privnet)) {
2532 2533
        testError(network->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Network '%s' is still running"), network->name);
2534
        goto cleanup;
2535 2536
    }

2537 2538
    virNetworkRemoveInactive(&privconn->networks,
                             privnet);
2539
    privnet = NULL;
2540
    ret = 0;
2541

2542
cleanup:
2543 2544 2545
    if (privnet)
        virNetworkObjUnlock(privnet);
    testDriverUnlock(privconn);
2546
    return ret;
2547 2548 2549
}

static int testNetworkStart(virNetworkPtr network) {
2550 2551
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
2552
    int ret = -1;
2553

2554
    testDriverLock(privconn);
2555 2556
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
2557
    testDriverUnlock(privconn);
2558 2559 2560

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2561
        goto cleanup;
2562
    }
2563

2564
    if (virNetworkIsActive(privnet)) {
2565 2566
        testError(network->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Network '%s' is already running"), network->name);
2567
        goto cleanup;
2568 2569
    }

2570
    privnet->active = 1;
2571
    ret = 0;
2572

2573
cleanup:
2574 2575
    if (privnet)
        virNetworkObjUnlock(privnet);
2576
    return ret;
2577 2578 2579
}

static int testNetworkDestroy(virNetworkPtr network) {
2580 2581
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
2582
    int ret = -1;
2583

2584
    testDriverLock(privconn);
2585 2586 2587 2588 2589
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2590
        goto cleanup;
2591
    }
2592

2593 2594 2595 2596
    privnet->active = 0;
    if (!privnet->persistent) {
        virNetworkRemoveInactive(&privconn->networks,
                                 privnet);
2597
        privnet = NULL;
2598
    }
2599 2600 2601
    ret = 0;

cleanup:
2602 2603 2604
    if (privnet)
        virNetworkObjUnlock(privnet);
    testDriverUnlock(privconn);
2605
    return ret;
2606 2607 2608
}

static char *testNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) {
2609 2610
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
2611
    char *ret = NULL;
2612

2613
    testDriverLock(privconn);
2614 2615
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
2616
    testDriverUnlock(privconn);
2617 2618 2619

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2620
        goto cleanup;
2621
    }
2622

2623 2624 2625
    ret = virNetworkDefFormat(network->conn, privnet->def);

cleanup:
2626 2627
    if (privnet)
        virNetworkObjUnlock(privnet);
2628
    return ret;
2629 2630 2631
}

static char *testNetworkGetBridgeName(virNetworkPtr network) {
2632
    testConnPtr privconn = network->conn->privateData;
2633
    char *bridge = NULL;
2634 2635
    virNetworkObjPtr privnet;

2636
    testDriverLock(privconn);
2637 2638
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
2639
    testDriverUnlock(privconn);
2640 2641 2642

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2643
        goto cleanup;
2644 2645
    }

2646 2647 2648 2649 2650 2651 2652 2653
    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))) {
2654
        virReportOOMError(network->conn);
2655
        goto cleanup;
2656
    }
2657 2658

cleanup:
2659 2660
    if (privnet)
        virNetworkObjUnlock(privnet);
2661 2662 2663 2664 2665
    return bridge;
}

static int testNetworkGetAutostart(virNetworkPtr network,
                                   int *autostart) {
2666 2667
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
2668
    int ret = -1;
2669

2670
    testDriverLock(privconn);
2671 2672
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
2673
    testDriverUnlock(privconn);
2674 2675 2676

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2677
        goto cleanup;
2678 2679
    }

2680
    *autostart = privnet->autostart;
2681 2682 2683
    ret = 0;

cleanup:
2684 2685
    if (privnet)
        virNetworkObjUnlock(privnet);
2686
    return ret;
2687 2688 2689 2690
}

static int testNetworkSetAutostart(virNetworkPtr network,
                                   int autostart) {
2691 2692
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
2693
    int ret = -1;
2694

2695
    testDriverLock(privconn);
2696 2697
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
2698
    testDriverUnlock(privconn);
2699 2700 2701

    if (privnet == NULL) {
        testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
2702
        goto cleanup;
2703 2704
    }

2705
    privnet->autostart = autostart ? 1 : 0;
2706 2707 2708
    ret = 0;

cleanup:
2709 2710
    if (privnet)
        virNetworkObjUnlock(privnet);
2711
    return ret;
2712
}
2713

C
Cole Robinson 已提交
2714

L
Laine Stump 已提交
2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 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 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 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 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022
/*
 * 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]);
        if (virInterfaceIsActive(privconn->ifaces.objs[i])) {
            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]);
        if (virInterfaceIsActive(privconn->ifaces.objs[i])) {
            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]);
        if (!virInterfaceIsActive(privconn->ifaces.objs[i])) {
            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]);
        if (!virInterfaceIsActive(privconn->ifaces.objs[i])) {
            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 已提交
3023 3024 3025 3026
/*
 * Storage Driver routines
 */

3027 3028
static int testStoragePoolObjSetDefaults(virConnectPtr conn,
                                         virStoragePoolObjPtr pool) {
C
Cole Robinson 已提交
3029 3030 3031 3032 3033 3034 3035

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

    pool->configFile = strdup("\0");
    if (!pool->configFile) {
3036
        virReportOOMError(conn);
C
Cole Robinson 已提交
3037 3038 3039 3040 3041 3042
        return -1;
    }

    return 0;
}

3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057
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 已提交
3058 3059 3060
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
                            const unsigned char *uuid) {
3061
    testConnPtr privconn = conn->privateData;
3062 3063
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3064

3065
    testDriverLock(privconn);
3066
    pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid);
3067
    testDriverUnlock(privconn);
3068 3069

    if (pool == NULL) {
C
Cole Robinson 已提交
3070
        testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL);
3071
        goto cleanup;
C
Cole Robinson 已提交
3072 3073
    }

3074 3075 3076
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
3077 3078
    if (pool)
        virStoragePoolObjUnlock(pool);
3079
    return ret;
C
Cole Robinson 已提交
3080 3081 3082 3083 3084
}

static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
                            const char *name) {
3085
    testConnPtr privconn = conn->privateData;
3086 3087
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3088

3089
    testDriverLock(privconn);
3090
    pool = virStoragePoolObjFindByName(&privconn->pools, name);
3091
    testDriverUnlock(privconn);
3092 3093

    if (pool == NULL) {
C
Cole Robinson 已提交
3094
        testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL);
3095
        goto cleanup;
C
Cole Robinson 已提交
3096 3097
    }

3098 3099 3100
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
3101 3102
    if (pool)
        virStoragePoolObjUnlock(pool);
3103
    return ret;
C
Cole Robinson 已提交
3104 3105 3106 3107 3108 3109 3110 3111 3112
}

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

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

3116
    testDriverLock(privconn);
C
Cole Robinson 已提交
3117 3118 3119
    for (i = 0 ; i < privconn->pools.count ; i++)
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numActive++;
3120
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3121 3122 3123 3124 3125 3126 3127 3128

    return numActive;
}

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

3132
    testDriverLock(privconn);
C
Cole Robinson 已提交
3133
    memset(names, 0, sizeof(*names)*nnames);
3134 3135
    for (i = 0 ; i < privconn->pools.count && n < nnames ; i++) {
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3136
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
3137 3138
            !(names[n++] = strdup(privconn->pools.objs[i]->def->name))) {
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3139
            goto no_memory;
3140 3141 3142 3143
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3144 3145 3146 3147

    return n;

no_memory:
3148
    virReportOOMError(conn);
C
Cole Robinson 已提交
3149 3150
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
3151
    testDriverUnlock(privconn);
3152
    return -1;
C
Cole Robinson 已提交
3153 3154 3155 3156
}

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

3160 3161 3162
    testDriverLock(privconn);
    for (i = 0 ; i < privconn->pools.count ; i++) {
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3163 3164
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numInactive++;
3165 3166 3167
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3168 3169 3170 3171 3172 3173 3174 3175

    return numInactive;
}

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

3179
    testDriverLock(privconn);
C
Cole Robinson 已提交
3180
    memset(names, 0, sizeof(*names)*nnames);
3181 3182
    for (i = 0 ; i < privconn->pools.count && n < nnames ; i++) {
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3183
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
3184 3185
            !(names[n++] = strdup(privconn->pools.objs[i]->def->name))) {
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3186
            goto no_memory;
3187 3188 3189 3190
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3191 3192 3193 3194

    return n;

no_memory:
3195
    virReportOOMError(conn);
C
Cole Robinson 已提交
3196 3197
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
3198
    testDriverUnlock(privconn);
3199
    return -1;
C
Cole Robinson 已提交
3200 3201 3202 3203
}


static int
3204
testStoragePoolStart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3205
                     unsigned int flags ATTRIBUTE_UNUSED) {
3206 3207
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3208
    int ret = -1;
3209

3210
    testDriverLock(privconn);
3211 3212
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3213
    testDriverUnlock(privconn);
3214 3215 3216

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

3220 3221 3222 3223 3224
    if (virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is already active"), pool->name);
        goto cleanup;
    }
C
Cole Robinson 已提交
3225 3226

    privpool->active = 1;
3227
    ret = 0;
C
Cole Robinson 已提交
3228

3229
cleanup:
3230 3231
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3232
    return ret;
C
Cole Robinson 已提交
3233 3234 3235
}

static char *
3236 3237 3238
testStorageFindPoolSources(virConnectPtr conn,
                           const char *type,
                           const char *srcSpec,
C
Cole Robinson 已提交
3239 3240
                           unsigned int flags ATTRIBUTE_UNUSED)
{
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 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285
    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 已提交
3286 3287 3288 3289 3290 3291 3292
}


static virStoragePoolPtr
testStoragePoolCreate(virConnectPtr conn,
                      const char *xml,
                      unsigned int flags ATTRIBUTE_UNUSED) {
3293
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
3294
    virStoragePoolDefPtr def;
3295
    virStoragePoolObjPtr pool = NULL;
3296
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3297

3298
    testDriverLock(privconn);
3299
    if (!(def = virStoragePoolDefParseString(conn, xml)))
3300
        goto cleanup;
C
Cole Robinson 已提交
3301

3302 3303 3304 3305
    pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid);
    if (!pool)
        pool = virStoragePoolObjFindByName(&privconn->pools, def->name);
    if (pool) {
C
Cole Robinson 已提交
3306 3307
        testError(conn, VIR_ERR_INTERNAL_ERROR,
                  "%s", _("storage pool already exists"));
3308
        goto cleanup;
C
Cole Robinson 已提交
3309 3310
    }

3311
    if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, def)))
3312
        goto cleanup;
3313
    def = NULL;
C
Cole Robinson 已提交
3314

3315
    if (testStoragePoolObjSetDefaults(conn, pool) == -1) {
C
Cole Robinson 已提交
3316
        virStoragePoolObjRemove(&privconn->pools, pool);
3317 3318
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
3319 3320 3321
    }
    pool->active = 1;

3322 3323 3324 3325
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
    virStoragePoolDefFree(def);
3326 3327 3328
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
3329
    return ret;
C
Cole Robinson 已提交
3330 3331 3332 3333 3334 3335
}

static virStoragePoolPtr
testStoragePoolDefine(virConnectPtr conn,
                      const char *xml,
                      unsigned int flags ATTRIBUTE_UNUSED) {
3336
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
3337
    virStoragePoolDefPtr def;
3338
    virStoragePoolObjPtr pool = NULL;
3339
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3340

3341
    testDriverLock(privconn);
3342
    if (!(def = virStoragePoolDefParseString(conn, xml)))
3343
        goto cleanup;
C
Cole Robinson 已提交
3344 3345 3346 3347 3348

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

3349
    if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, def)))
3350 3351
        goto cleanup;
    def = NULL;
C
Cole Robinson 已提交
3352

3353
    if (testStoragePoolObjSetDefaults(conn, pool) == -1) {
C
Cole Robinson 已提交
3354
        virStoragePoolObjRemove(&privconn->pools, pool);
3355 3356
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
3357 3358
    }

3359 3360 3361 3362
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
    virStoragePoolDefFree(def);
3363 3364 3365
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
3366
    return ret;
C
Cole Robinson 已提交
3367 3368 3369
}

static int
3370 3371 3372
testStoragePoolUndefine(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3373
    int ret = -1;
3374

3375
    testDriverLock(privconn);
3376 3377 3378 3379 3380
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

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

3384 3385 3386 3387 3388
    if (virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is already active"), pool->name);
        goto cleanup;
    }
C
Cole Robinson 已提交
3389 3390

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

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

static int
3401
testStoragePoolBuild(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3402
                     unsigned int flags ATTRIBUTE_UNUSED) {
3403 3404
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3405
    int ret = -1;
3406

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

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

3417 3418 3419 3420 3421
    if (virStoragePoolObjIsActive(privpool)) {
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is already active"), pool->name);
        goto cleanup;
    }
3422
    ret = 0;
C
Cole Robinson 已提交
3423

3424
cleanup:
3425 3426
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3427
    return ret;
C
Cole Robinson 已提交
3428 3429 3430 3431
}


static int
3432 3433 3434
testStoragePoolDestroy(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3435
    int ret = -1;
3436

3437
    testDriverLock(privconn);
3438 3439 3440 3441 3442
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3443
        goto cleanup;
3444 3445 3446 3447 3448
    }

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

    privpool->active = 0;

3454
    if (privpool->configFile == NULL) {
C
Cole Robinson 已提交
3455
        virStoragePoolObjRemove(&privconn->pools, privpool);
3456 3457
        privpool = NULL;
    }
3458
    ret = 0;
C
Cole Robinson 已提交
3459

3460
cleanup:
3461 3462 3463
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
3464
    return ret;
C
Cole Robinson 已提交
3465 3466 3467 3468
}


static int
3469
testStoragePoolDelete(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3470
                      unsigned int flags ATTRIBUTE_UNUSED) {
3471 3472
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3473
    int ret = -1;
3474

3475
    testDriverLock(privconn);
3476 3477
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3478
    testDriverUnlock(privconn);
3479 3480 3481

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3482 3483 3484 3485 3486 3487 3488
        goto cleanup;
    }

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

3491
    ret = 0;
C
Cole Robinson 已提交
3492

3493
cleanup:
3494 3495
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3496
    return ret;
C
Cole Robinson 已提交
3497 3498 3499 3500
}


static int
3501
testStoragePoolRefresh(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3502
                       unsigned int flags ATTRIBUTE_UNUSED) {
3503 3504
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3505
    int ret = -1;
3506

3507
    testDriverLock(privconn);
3508 3509
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3510
    testDriverUnlock(privconn);
3511 3512 3513

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3514
        goto cleanup;
3515 3516 3517 3518 3519
    }

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

3524
cleanup:
3525 3526
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3527
    return ret;
C
Cole Robinson 已提交
3528 3529 3530 3531
}


static int
3532
testStoragePoolGetInfo(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3533
                       virStoragePoolInfoPtr info) {
3534 3535
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3536
    int ret = -1;
3537

3538
    testDriverLock(privconn);
3539 3540
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3541
    testDriverUnlock(privconn);
3542 3543 3544

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3545
        goto cleanup;
3546
    }
C
Cole Robinson 已提交
3547 3548 3549 3550 3551 3552 3553 3554 3555

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

3558
cleanup:
3559 3560
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3561
    return ret;
C
Cole Robinson 已提交
3562 3563 3564
}

static char *
3565
testStoragePoolDumpXML(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3566
                       unsigned int flags ATTRIBUTE_UNUSED) {
3567 3568
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3569
    char *ret = NULL;
3570

3571
    testDriverLock(privconn);
3572 3573
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3574
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3575

3576 3577
    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3578
        goto cleanup;
3579 3580
    }

3581 3582 3583
    ret = virStoragePoolDefFormat(pool->conn, privpool->def);

cleanup:
3584 3585
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3586
    return ret;
C
Cole Robinson 已提交
3587 3588 3589
}

static int
3590
testStoragePoolGetAutostart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3591
                            int *autostart) {
3592 3593
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3594
    int ret = -1;
3595

3596
    testDriverLock(privconn);
3597 3598
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3599
    testDriverUnlock(privconn);
3600 3601 3602

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3603
        goto cleanup;
3604
    }
C
Cole Robinson 已提交
3605 3606 3607 3608 3609 3610

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

3613
cleanup:
3614 3615
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3616
    return ret;
C
Cole Robinson 已提交
3617 3618 3619
}

static int
3620
testStoragePoolSetAutostart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3621
                            int autostart) {
3622 3623
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3624
    int ret = -1;
3625

3626
    testDriverLock(privconn);
3627 3628
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3629
    testDriverUnlock(privconn);
3630 3631 3632

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3633
        goto cleanup;
3634
    }
C
Cole Robinson 已提交
3635 3636

    if (!privpool->configFile) {
3637
        testError(pool->conn, VIR_ERR_INVALID_ARG,
C
Cole Robinson 已提交
3638
                  "%s", _("pool has no config file"));
3639
        goto cleanup;
C
Cole Robinson 已提交
3640 3641 3642 3643
    }

    autostart = (autostart != 0);
    privpool->autostart = autostart;
3644 3645 3646
    ret = 0;

cleanup:
3647 3648
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3649
    return ret;
C
Cole Robinson 已提交
3650 3651 3652 3653
}


static int
3654 3655 3656
testStoragePoolNumVolumes(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3657
    int ret = -1;
3658

3659
    testDriverLock(privconn);
3660 3661
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3662
    testDriverUnlock(privconn);
3663 3664 3665

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3666
        goto cleanup;
3667 3668 3669 3670 3671
    }

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

3675 3676 3677
    ret = privpool->volumes.count;

cleanup:
3678 3679
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3680
    return ret;
C
Cole Robinson 已提交
3681 3682 3683
}

static int
3684
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3685 3686
                           char **const names,
                           int maxnames) {
3687 3688
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
C
Cole Robinson 已提交
3689 3690
    int i = 0, n = 0;

3691
    memset(names, 0, maxnames * sizeof(*names));
3692 3693

    testDriverLock(privconn);
3694 3695
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3696
    testDriverUnlock(privconn);
3697 3698 3699

    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3700
        goto cleanup;
3701 3702 3703 3704 3705 3706
    }


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

C
Cole Robinson 已提交
3710 3711
    for (i = 0 ; i < privpool->volumes.count && n < maxnames ; i++) {
        if ((names[n++] = strdup(privpool->volumes.objs[i]->name)) == NULL) {
3712
            virReportOOMError(pool->conn);
C
Cole Robinson 已提交
3713 3714 3715 3716
            goto cleanup;
        }
    }

3717
    virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
3718 3719 3720 3721 3722 3723
    return n;

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

3724
    memset(names, 0, maxnames * sizeof(*names));
3725 3726
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
3727 3728 3729 3730 3731
    return -1;
}


static virStorageVolPtr
3732
testStorageVolumeLookupByName(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3733
                              const char *name ATTRIBUTE_UNUSED) {
3734 3735 3736
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
3737
    virStorageVolPtr ret = NULL;
3738

3739
    testDriverLock(privconn);
3740 3741
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3742
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3743

3744 3745
    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3746
        goto cleanup;
3747 3748 3749 3750 3751 3752
    }


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

    privvol = virStorageVolDefFindByName(privpool, name);

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

3764 3765 3766 3767
    ret = virGetStorageVol(pool->conn, privpool->def->name,
                           privvol->name, privvol->key);

cleanup:
3768 3769
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3770
    return ret;
C
Cole Robinson 已提交
3771 3772 3773 3774 3775 3776
}


static virStorageVolPtr
testStorageVolumeLookupByKey(virConnectPtr conn,
                             const char *key) {
3777
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
3778
    unsigned int i;
3779
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
3780

3781
    testDriverLock(privconn);
C
Cole Robinson 已提交
3782
    for (i = 0 ; i < privconn->pools.count ; i++) {
3783
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3784
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
3785
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
3786 3787
                virStorageVolDefFindByKey(privconn->pools.objs[i], key);

3788 3789 3790 3791 3792
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
                                       privvol->key);
3793
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
3794 3795
                break;
            }
C
Cole Robinson 已提交
3796
        }
3797
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3798
    }
3799
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3800

3801 3802 3803 3804 3805
    if (!ret)
        testError(conn, VIR_ERR_INVALID_STORAGE_VOL,
                  _("no storage vol with matching key '%s'"), key);

    return ret;
C
Cole Robinson 已提交
3806 3807 3808 3809 3810
}

static virStorageVolPtr
testStorageVolumeLookupByPath(virConnectPtr conn,
                              const char *path) {
3811
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
3812
    unsigned int i;
3813
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
3814

3815
    testDriverLock(privconn);
C
Cole Robinson 已提交
3816
    for (i = 0 ; i < privconn->pools.count ; i++) {
3817
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3818
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
3819
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
3820 3821
                virStorageVolDefFindByPath(privconn->pools.objs[i], path);

3822 3823 3824 3825 3826
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
                                       privvol->key);
3827
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
3828 3829
                break;
            }
C
Cole Robinson 已提交
3830
        }
3831
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3832
    }
3833
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3834

3835 3836 3837 3838 3839
    if (!ret)
        testError(conn, VIR_ERR_INVALID_STORAGE_VOL,
                  _("no storage vol with matching path '%s'"), path);

    return ret;
C
Cole Robinson 已提交
3840 3841 3842
}

static virStorageVolPtr
3843
testStorageVolumeCreateXML(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3844 3845
                           const char *xmldesc,
                           unsigned int flags ATTRIBUTE_UNUSED) {
3846 3847
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3848 3849
    virStorageVolDefPtr privvol = NULL;
    virStorageVolPtr ret = NULL;
3850

3851
    testDriverLock(privconn);
3852 3853
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3854
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3855

3856 3857
    if (privpool == NULL) {
        testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
3858
        goto cleanup;
3859 3860 3861 3862 3863
    }

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

3867
    privvol = virStorageVolDefParseString(pool->conn, privpool->def, xmldesc);
3868
    if (privvol == NULL)
3869
        goto cleanup;
3870 3871

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
3872
        testError(pool->conn, VIR_ERR_INVALID_STORAGE_VOL,
C
Cole Robinson 已提交
3873
                  "%s", _("storage vol already exists"));
3874
        goto cleanup;
C
Cole Robinson 已提交
3875 3876 3877
    }

    /* Make sure enough space */
3878
    if ((privpool->def->allocation + privvol->allocation) >
C
Cole Robinson 已提交
3879
         privpool->def->capacity) {
3880
        testError(pool->conn, VIR_ERR_INTERNAL_ERROR,
C
Cole Robinson 已提交
3881
                  _("Not enough free space in pool for volume '%s'"),
3882
                  privvol->name);
3883
        goto cleanup;
C
Cole Robinson 已提交
3884 3885 3886 3887
    }

    if (VIR_REALLOC_N(privpool->volumes.objs,
                      privpool->volumes.count+1) < 0) {
3888
        virReportOOMError(pool->conn);
3889
        goto cleanup;
C
Cole Robinson 已提交
3890 3891
    }

3892 3893 3894
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
                    privvol->name) == -1) {
3895
        virReportOOMError(pool->conn);
3896
        goto cleanup;
C
Cole Robinson 已提交
3897 3898
    }

3899 3900
    privvol->key = strdup(privvol->target.path);
    if (privvol->key == NULL) {
3901
        virReportOOMError(pool->conn);
3902
        goto cleanup;
C
Cole Robinson 已提交
3903 3904
    }

3905
    privpool->def->allocation += privvol->allocation;
C
Cole Robinson 已提交
3906 3907 3908
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

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

3911 3912
    ret = virGetStorageVol(pool->conn, privpool->def->name,
                           privvol->name, privvol->key);
3913
    privvol = NULL;
3914 3915 3916

cleanup:
    virStorageVolDefFree(privvol);
3917 3918
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3919
    return ret;
C
Cole Robinson 已提交
3920 3921
}

3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947
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;
    }

3948
    privvol = virStorageVolDefParseString(pool->conn, privpool->def, xmldesc);
3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982
    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;
    }

3983 3984 3985
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
                    privvol->name) == -1) {
3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012
        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 已提交
4013
static int
4014
testStorageVolumeDelete(virStorageVolPtr vol,
C
Cole Robinson 已提交
4015
                        unsigned int flags ATTRIBUTE_UNUSED) {
4016 4017 4018
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
C
Cole Robinson 已提交
4019
    int i;
4020
    int ret = -1;
C
Cole Robinson 已提交
4021

4022
    testDriverLock(privconn);
4023 4024
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
4025
    testDriverUnlock(privconn);
4026 4027 4028

    if (privpool == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
4029
        goto cleanup;
4030 4031 4032 4033 4034 4035 4036 4037 4038
    }


    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);
4039
        goto cleanup;
4040 4041 4042 4043 4044
    }

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


C
Cole Robinson 已提交
4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071
    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;
        }
    }
4072
    ret = 0;
C
Cole Robinson 已提交
4073

4074
cleanup:
4075 4076
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4077
    return ret;
C
Cole Robinson 已提交
4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093
}


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
4094
testStorageVolumeGetInfo(virStorageVolPtr vol,
C
Cole Robinson 已提交
4095
                         virStorageVolInfoPtr info) {
4096 4097 4098
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
4099
    int ret = -1;
4100

4101
    testDriverLock(privconn);
4102 4103
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
4104
    testDriverUnlock(privconn);
4105 4106 4107

    if (privpool == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
4108
        goto cleanup;
4109 4110 4111 4112 4113 4114 4115 4116
    }

    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);
4117
        goto cleanup;
4118 4119 4120 4121 4122
    }

    if (!virStoragePoolObjIsActive(privpool)) {
        testError(vol->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is not active"), vol->pool);
4123
        goto cleanup;
4124
    }
C
Cole Robinson 已提交
4125 4126 4127 4128 4129

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

4132
cleanup:
4133 4134
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4135
    return ret;
C
Cole Robinson 已提交
4136 4137 4138
}

static char *
4139
testStorageVolumeGetXMLDesc(virStorageVolPtr vol,
C
Cole Robinson 已提交
4140
                            unsigned int flags ATTRIBUTE_UNUSED) {
4141 4142 4143
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
4144
    char *ret = NULL;
4145

4146
    testDriverLock(privconn);
4147 4148
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
4149
    testDriverUnlock(privconn);
4150 4151 4152

    if (privpool == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
4153
        goto cleanup;
4154 4155 4156 4157 4158 4159 4160 4161
    }

    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);
4162
        goto cleanup;
4163
    }
C
Cole Robinson 已提交
4164

4165 4166 4167
    if (!virStoragePoolObjIsActive(privpool)) {
        testError(vol->conn, VIR_ERR_INTERNAL_ERROR,
                  _("storage pool '%s' is not active"), vol->pool);
4168
        goto cleanup;
4169 4170
    }

4171 4172 4173
    ret = virStorageVolDefFormat(vol->conn, privpool->def, privvol);

cleanup:
4174 4175
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4176
    return ret;
C
Cole Robinson 已提交
4177 4178 4179
}

static char *
4180 4181 4182 4183
testStorageVolumeGetPath(virStorageVolPtr vol) {
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
4184
    char *ret = NULL;
4185

4186
    testDriverLock(privconn);
4187 4188
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
4189
    testDriverUnlock(privconn);
4190 4191 4192

    if (privpool == NULL) {
        testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
4193
        goto cleanup;
4194 4195 4196 4197 4198 4199 4200 4201
    }

    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);
4202
        goto cleanup;
4203 4204 4205 4206 4207
    }

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

C
Cole Robinson 已提交
4211
    ret = strdup(privvol->target.path);
4212
    if (ret == NULL)
4213
        virReportOOMError(vol->conn);
4214 4215

cleanup:
4216 4217
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4218 4219 4220
    return ret;
}

4221

4222
/* Node device implementations */
4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237
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;
}

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 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375
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;
}

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 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445
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;
}

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 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570
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;
}

4571 4572

/* Domain event implementations */
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 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668
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);
}

4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682
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;
}
4683

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

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 已提交
4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793
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 */
};


4794 4795 4796 4797
static virStorageDriver testStorageDriver = {
    .name = "Test",
    .open = testStorageOpen,
    .close = testStorageClose,
C
Cole Robinson 已提交
4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825

    .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,
4826
    .volCreateXMLFrom = testStorageVolumeCreateXMLFrom,
C
Cole Robinson 已提交
4827 4828 4829 4830
    .volDelete = testStorageVolumeDelete,
    .volGetInfo = testStorageVolumeGetInfo,
    .volGetXMLDesc = testStorageVolumeGetXMLDesc,
    .volGetPath = testStorageVolumeGetPath,
4831 4832
};

4833 4834 4835 4836
static virDeviceMonitor testDevMonitor = {
    .name = "Test",
    .open = testDevMonOpen,
    .close = testDevMonClose,
4837 4838 4839 4840 4841 4842 4843 4844

    .numOfDevices = testNodeNumOfDevices,
    .listDevices = testNodeListDevices,
    .deviceLookupByName = testNodeDeviceLookupByName,
    .deviceDumpXML = testNodeDeviceDumpXML,
    .deviceGetParent = testNodeDeviceGetParent,
    .deviceNumOfCaps = testNodeDeviceNumOfCaps,
    .deviceListCaps = testNodeDeviceListCaps,
4845 4846
    .deviceCreateXML = testNodeDeviceCreateXML,
    .deviceDestroy = testNodeDeviceDestroy,
4847 4848
};

4849 4850 4851 4852 4853
static virSecretDriver testSecretDriver = {
    .name = "Test",
    .open = testSecretOpen,
    .close = testSecretClose,
};
4854 4855


4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
    if (virRegisterDriver(&testDriver) < 0)
        return -1;
    if (virRegisterNetworkDriver(&testNetworkDriver) < 0)
        return -1;
L
Laine Stump 已提交
4868 4869
    if (virRegisterInterfaceDriver(&testInterfaceDriver) < 0)
        return -1;
4870 4871
    if (virRegisterStorageDriver(&testStorageDriver) < 0)
        return -1;
4872 4873
    if (virRegisterDeviceMonitor(&testDevMonitor) < 0)
        return -1;
4874 4875
    if (virRegisterSecretDriver(&testSecretDriver) < 0)
        return -1;
4876

4877 4878
    return 0;
}