test_driver.c 167.8 KB
Newer Older
1 2 3
/*
 * test.c: A "mock" hypervisor for use by application unit tests
 *
4
 * Copyright (C) 2006-2012 Red Hat, Inc.
5
 * Copyright (C) 2006 Daniel P. Berrange
6
 *
7 8 9 10 11 12 13 14 15 16 17
 * 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
18
 * License along with this library.  If not, see
O
Osier Yang 已提交
19
 * <http://www.gnu.org/licenses/>.
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 "virerror.h"
36
#include "datatypes.h"
37
#include "test_driver.h"
38
#include "virbuffer.h"
39
#include "viruuid.h"
40
#include "capabilities.h"
41
#include "configmake.h"
42
#include "viralloc.h"
43
#include "network_conf.h"
L
Laine Stump 已提交
44
#include "interface_conf.h"
45
#include "domain_conf.h"
46
#include "domain_event.h"
47
#include "fdstream.h"
C
Cole Robinson 已提交
48
#include "storage_conf.h"
49
#include "node_device_conf.h"
50
#include "virxml.h"
51
#include "virthread.h"
52
#include "virlog.h"
E
Eric Blake 已提交
53
#include "virfile.h"
54
#include "virtypedparam.h"
55
#include "virrandom.h"
56
#include "virstring.h"
57

58 59
#define VIR_FROM_THIS VIR_FROM_TEST

60 61 62 63 64 65 66 67 68
/* Driver specific info to carry with a domain */
struct _testDomainObjPrivate {
    virVcpuInfoPtr vcpu_infos;

    unsigned char *cpumaps;
};
typedef struct _testDomainObjPrivate testDomainObjPrivate;
typedef struct _testDomainObjPrivate *testDomainObjPrivatePtr;

69 70 71 72 73
#define MAX_CPUS 128

struct _testCell {
    unsigned long mem;
    int numCpus;
74
    virCapsHostNUMACellCPU cpus[MAX_CPUS];
75 76 77 78 79
};
typedef struct _testCell testCell;
typedef struct _testCell *testCellPtr;

#define MAX_CELLS 128
80

81
struct _testConn {
82
    virMutex lock;
83

E
Eric Blake 已提交
84
    char *path;
85
    int nextDomID;
86
    virCapsPtr caps;
87
    virDomainXMLOptionPtr xmlopt;
88
    virNodeInfo nodeInfo;
89
    virDomainObjListPtr domains;
90
    virNetworkObjList networks;
L
Laine Stump 已提交
91
    virInterfaceObjList ifaces;
92 93
    bool transaction_running;
    virInterfaceObjList backupIfaces;
C
Cole Robinson 已提交
94
    virStoragePoolObjList pools;
95
    virNodeDeviceObjList devs;
96 97
    int numCells;
    testCell cells[MAX_CELLS];
98

99
    virDomainEventStatePtr domainEventState;
100 101 102
};
typedef struct _testConn testConn;
typedef struct _testConn *testConnPtr;
103

104
#define TEST_MODEL "i686"
105
#define TEST_MODEL_WORDSIZE 32
106
#define TEST_EMULATOR "/usr/bin/test-hv"
107

108
static const virNodeInfo defaultNodeInfo = {
109
    TEST_MODEL,
110 111 112 113 114 115 116
    1024*1024*3, /* 3 GB */
    16,
    1400,
    2,
    2,
    2,
    2,
117 118
};

119

120
static int testConnectClose(virConnectPtr conn);
121 122 123 124
static void testDomainEventQueue(testConnPtr driver,
                                 virDomainEventPtr event);


125 126
static void testDriverLock(testConnPtr driver)
{
127
    virMutexLock(&driver->lock);
128 129 130 131
}

static void testDriverUnlock(testConnPtr driver)
{
132
    virMutexUnlock(&driver->lock);
133 134
}

135 136 137 138 139 140 141 142 143 144 145 146 147 148
static void *testDomainObjPrivateAlloc(void)
{
    testDomainObjPrivatePtr priv;

    if (VIR_ALLOC(priv) < 0)
        return NULL;

    return priv;
}

static void testDomainObjPrivateFree(void *data)
{
    testDomainObjPrivatePtr priv = data;

D
Daniel P. Berrange 已提交
149
    VIR_FREE(priv->vcpu_infos);
150 151 152 153 154
    VIR_FREE(priv->cpumaps);
    VIR_FREE(priv);
}


155
static virDomainXMLOptionPtr
156 157 158 159
testBuildXMLConfig(void)
{
    virDomainXMLPrivateDataCallbacks priv = { .alloc = testDomainObjPrivateAlloc,
                                              .free = testDomainObjPrivateFree };
160
    return virDomainXMLOptionNew(NULL, &priv, NULL);
161 162 163
}


164 165
static virCapsPtr
testBuildCapabilities(virConnectPtr conn) {
166
    testConnPtr privconn = conn->privateData;
167 168 169
    virCapsPtr caps;
    virCapsGuestPtr guest;
    const char *const guest_types[] = { "hvm", "xen" };
170
    size_t i;
171

172
    if ((caps = virCapabilitiesNew(VIR_ARCH_I686, 0, 0)) == NULL)
173
        goto error;
174

175
    if (virCapabilitiesAddHostFeature(caps, "pae") < 0)
176
        goto error;
177
    if (virCapabilitiesAddHostFeature(caps ,"nonpae") < 0)
178
        goto error;
179

180
    for (i = 0; i < privconn->numCells; i++) {
181 182 183
        virCapsHostNUMACellCPUPtr cpu_cells;

        if (VIR_ALLOC_N(cpu_cells, privconn->cells[i].numCpus) < 0)
184
            goto error;
185 186 187 188 189

        memcpy(cpu_cells, privconn->cells[i].cpus,
               sizeof(*cpu_cells) * privconn->cells[i].numCpus);


190
        if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].numCpus,
191
                                           0, cpu_cells) < 0)
192
            goto error;
193 194
    }

195
    for (i = 0; i < ARRAY_CARDINALITY(guest_types); i++) {
196 197
        if ((guest = virCapabilitiesAddGuest(caps,
                                             guest_types[i],
198
                                             VIR_ARCH_I686,
199 200 201 202
                                             TEST_EMULATOR,
                                             NULL,
                                             0,
                                             NULL)) == NULL)
203
            goto error;
204

205 206 207 208 209 210
        if (virCapabilitiesAddGuestDomain(guest,
                                          "test",
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
211
            goto error;
212

213
        if (virCapabilitiesAddGuestFeature(guest, "pae", 1, 1) == NULL)
214
            goto error;
215
        if (virCapabilitiesAddGuestFeature(guest ,"nonpae", 1, 1) == NULL)
216
            goto error;
217 218
    }

219 220
    caps->host.nsecModels = 1;
    if (VIR_ALLOC_N(caps->host.secModels, caps->host.nsecModels) < 0)
221
        goto error;
222 223
    if (VIR_STRDUP(caps->host.secModels[0].model, "testSecurity") < 0)
        goto error;
224

225 226
    if (VIR_STRDUP(caps->host.secModels[0].doi, "") < 0)
        goto error;
227

228
    return caps;
229

230
error:
231
    virObjectUnref(caps);
232
    return NULL;
233 234
}

235

236 237 238
static const char *defaultDomainXML =
"<domain type='test'>"
"  <name>test</name>"
239
"  <uuid>6695eb01-f6a4-8304-79aa-97f2502e193f</uuid>"
240 241 242 243 244 245 246
"  <memory>8388608</memory>"
"  <currentMemory>2097152</currentMemory>"
"  <vcpu>2</vcpu>"
"  <os>"
"    <type>hvm</type>"
"  </os>"
"</domain>";
247 248


249 250 251
static const char *defaultNetworkXML =
"<network>"
"  <name>default</name>"
252
"  <uuid>dd8fe884-6c02-601e-7551-cca97df1c5df</uuid>"
253 254 255 256 257 258 259 260
"  <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>";
261

L
Laine Stump 已提交
262 263 264 265 266 267 268 269 270 271 272
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 已提交
273 274 275
static const char *defaultPoolXML =
"<pool type='dir'>"
"  <name>default-pool</name>"
276
"  <uuid>dfe224cb-28fb-8dd0-c4b2-64eb3f0f4566</uuid>"
C
Cole Robinson 已提交
277 278 279 280 281
"  <target>"
"    <path>/default-pool</path>"
"  </target>"
"</pool>";

282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
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";

305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
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>";

323
static const unsigned long long defaultPoolCap = (100 * 1024 * 1024 * 1024ull);
C
Cole Robinson 已提交
324 325
static const unsigned long long defaultPoolAlloc = 0;

326
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool);
327
static int testNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
328

329
static char *
330
testDomainGenerateIfname(virDomainDefPtr domdef) {
331
    int maxif = 1024;
332 333
    int ifctr;
    size_t i;
334 335 336 337 338

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

339
        if (virAsprintf(&ifname, "testnet%d", ifctr) < 0)
340 341 342
            return NULL;

        /* Generate network interface names */
343
        for (i = 0; i < domdef->nnets; i++) {
344
            if (domdef->nets[i]->ifname &&
345
                STREQ(domdef->nets[i]->ifname, ifname)) {
346 347 348 349 350 351 352 353 354
                found = 1;
                break;
            }
        }

        if (!found)
            return ifname;
    }

355 356
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Exceeded max iface limit %d"), maxif);
357 358 359
    return NULL;
}

360
static int
361
testDomainGenerateIfnames(virDomainDefPtr domdef)
362
{
363
    size_t i = 0;
364 365 366 367 368 369

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

370
        ifname = testDomainGenerateIfname(domdef);
371
        if (!ifname)
372
            return -1;
373 374 375 376

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

377
    return 0;
378 379
}

380 381 382 383 384 385 386 387 388 389 390
/* Helper to update info for a single VCPU */
static int
testDomainUpdateVCPU(virConnectPtr conn ATTRIBUTE_UNUSED,
                     virDomainObjPtr dom,
                     int vcpu,
                     int maplen,
                     int maxcpu)
{
    testDomainObjPrivatePtr privdata = dom->privateData;
    virVcpuInfoPtr info = &privdata->vcpu_infos[vcpu];
    unsigned char *cpumap = VIR_GET_CPUMAP(privdata->cpumaps, maplen, vcpu);
391
    size_t j;
H
Hu Tao 已提交
392
    bool cpu;
393 394 395 396 397 398 399 400 401 402 403

    memset(info, 0, sizeof(virVcpuInfo));
    memset(cpumap, 0, maplen);

    info->number    = vcpu;
    info->state     = VIR_VCPU_RUNNING;
    info->cpuTime   = 5000000;
    info->cpu       = 0;

    if (dom->def->cpumask) {
        for (j = 0; j < maxcpu && j < VIR_DOMAIN_CPUMASK_LEN; ++j) {
H
Hu Tao 已提交
404 405 406
            if (virBitmapGetBit(dom->def->cpumask, j, &cpu) < 0)
                return -1;
            if (cpu) {
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
                VIR_USE_CPU(cpumap, j);
                info->cpu = j;
            }
        }
    } else {
        for (j = 0; j < maxcpu; ++j) {
            if ((j % 3) == 0) {
                /* Mark of every third CPU as usable */
                VIR_USE_CPU(cpumap, j);
                info->cpu = j;
            }
        }
    }

    return 0;
}

/*
 * Update domain VCPU amount and info
 *
 * @conn: virConnectPtr
 * @dom : domain needing updates
 * @nvcpus: New amount of vcpus for the domain
 * @clear_all: If true, rebuild info for ALL vcpus, not just newly added vcpus
 */
static int
testDomainUpdateVCPUs(virConnectPtr conn,
                      virDomainObjPtr dom,
                      int nvcpus,
                      unsigned int clear_all)
{
    testConnPtr privconn = conn->privateData;
    testDomainObjPrivatePtr privdata = dom->privateData;
440 441
    size_t i;
    int ret = -1;
442 443 444 445 446
    int cpumaplen, maxcpu;

    maxcpu  = VIR_NODEINFO_MAXCPUS(privconn->nodeInfo);
    cpumaplen = VIR_CPU_MAPLEN(maxcpu);

447
    if (VIR_REALLOC_N(privdata->vcpu_infos, nvcpus) < 0)
448 449
        goto cleanup;

450
    if (VIR_REALLOC_N(privdata->cpumaps, nvcpus * cpumaplen) < 0)
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
        goto cleanup;

    /* Set running VCPU and cpumap state */
    if (clear_all) {
        for (i = 0; i < nvcpus; ++i)
            if (testDomainUpdateVCPU(conn, dom, i, cpumaplen, maxcpu) < 0)
                goto cleanup;

    } else if (nvcpus > dom->def->vcpus) {
        /* VCPU amount has grown, populate info for the new vcpus */
        for (i = dom->def->vcpus; i < nvcpus; ++i)
            if (testDomainUpdateVCPU(conn, dom, i, cpumaplen, maxcpu) < 0)
                goto cleanup;
    }

466
    dom->def->vcpus = nvcpus;
467 468 469 470 471
    ret = 0;
cleanup:
    return ret;
}

472 473
static void
testDomainShutdownState(virDomainPtr domain,
J
Jiri Denemark 已提交
474 475
                        virDomainObjPtr privdom,
                        virDomainShutoffReason reason)
476 477 478 479 480 481 482
{
    if (privdom->newDef) {
        virDomainDefFree(privdom->def);
        privdom->def = privdom->newDef;
        privdom->newDef = NULL;
    }

J
Jiri Denemark 已提交
483
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF, reason);
484 485 486 487 488
    privdom->def->id = -1;
    if (domain)
        domain->id = -1;
}

489
/* Set up domain runtime state */
490 491
static int
testDomainStartState(virConnectPtr conn,
J
Jiri Denemark 已提交
492 493
                     virDomainObjPtr dom,
                     virDomainRunningReason reason)
494 495
{
    testConnPtr privconn = conn->privateData;
496
    int ret = -1;
497

498 499 500
    if (testDomainUpdateVCPUs(conn, dom, dom->def->vcpus, 1) < 0)
        goto cleanup;

J
Jiri Denemark 已提交
501
    virDomainObjSetState(dom, VIR_DOMAIN_RUNNING, reason);
502 503
    dom->def->id = privconn->nextDomID++;

504
    if (virDomainObjSetDefTransient(privconn->caps,
505
                                    privconn->xmlopt,
506
                                    dom, false) < 0) {
507 508 509
        goto cleanup;
    }

510 511
    ret = 0;
cleanup:
512
    if (ret < 0)
J
Jiri Denemark 已提交
513
        testDomainShutdownState(NULL, dom, VIR_DOMAIN_SHUTOFF_FAILED);
514
    return ret;
515
}
516

517
static int testOpenDefault(virConnectPtr conn) {
518
    int u;
519
    testConnPtr privconn;
520 521 522 523
    virDomainDefPtr domdef = NULL;
    virDomainObjPtr domobj = NULL;
    virNetworkDefPtr netdef = NULL;
    virNetworkObjPtr netobj = NULL;
L
Laine Stump 已提交
524 525
    virInterfaceDefPtr interfacedef = NULL;
    virInterfaceObjPtr interfaceobj = NULL;
C
Cole Robinson 已提交
526 527
    virStoragePoolDefPtr pooldef = NULL;
    virStoragePoolObjPtr poolobj = NULL;
528 529
    virNodeDeviceDefPtr nodedef = NULL;
    virNodeDeviceObjPtr nodeobj = NULL;
530

531
    if (VIR_ALLOC(privconn) < 0)
532
        return VIR_DRV_OPEN_ERROR;
533
    if (virMutexInit(&privconn->lock) < 0) {
534 535
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot initialize mutex"));
536 537 538 539
        VIR_FREE(privconn);
        return VIR_DRV_OPEN_ERROR;
    }

540
    testDriverLock(privconn);
541
    conn->privateData = privconn;
542

543
    if (!(privconn->domains = virDomainObjListNew()))
544 545
        goto error;

546
    memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));
547

548
    /* Numa setup */
549 550 551 552 553
    privconn->numCells = 2;
    for (u = 0; u < 2; ++u) {
        privconn->cells[u].numCpus = 8;
        privconn->cells[u].mem = (u + 1) * 2048 * 1024;
    }
554
    for (u = 0; u < 16; u++) {
555
        virBitmapPtr siblings = virBitmapNew(16);
556
        if (!siblings)
557 558 559 560 561 562
            goto error;
        ignore_value(virBitmapSetBit(siblings, u));
        privconn->cells[u / 8].cpus[(u % 8)].id = u;
        privconn->cells[u / 8].cpus[(u % 8)].socket_id = u / 8;
        privconn->cells[u / 8].cpus[(u % 8)].core_id = u % 8;
        privconn->cells[u / 8].cpus[(u % 8)].siblings = siblings;
563 564
    }

565 566 567
    if (!(privconn->caps = testBuildCapabilities(conn)))
        goto error;

568
    if (!(privconn->xmlopt = testBuildXMLConfig()))
569 570
        goto error;

571 572
    privconn->nextDomID = 1;

573 574
    if (!(domdef = virDomainDefParseString(defaultDomainXML,
                                           privconn->caps,
575
                                           privconn->xmlopt,
M
Matthias Bolte 已提交
576
                                           1 << VIR_DOMAIN_VIRT_TEST,
577
                                           VIR_DOMAIN_XML_INACTIVE)))
578
        goto error;
M
Matthias Bolte 已提交
579

580
    if (testDomainGenerateIfnames(domdef) < 0)
581
        goto error;
582
    if (!(domobj = virDomainObjListAdd(privconn->domains,
583
                                       domdef,
584
                                       privconn->xmlopt,
585
                                       0, NULL)))
586 587
        goto error;
    domdef = NULL;
588

589
    domobj->persistent = 1;
J
Jiri Denemark 已提交
590
    if (testDomainStartState(conn, domobj, VIR_DOMAIN_RUNNING_BOOTED) < 0) {
591
        virObjectUnlock(domobj);
592 593 594
        goto error;
    }

595
    virObjectUnlock(domobj);
596

597
    if (!(netdef = virNetworkDefParseString(defaultNetworkXML)))
598
        goto error;
599
    if (!(netobj = virNetworkAssignDef(&privconn->networks, netdef, false))) {
600 601 602 603 604
        virNetworkDefFree(netdef);
        goto error;
    }
    netobj->active = 1;
    netobj->persistent = 1;
605
    virNetworkObjUnlock(netobj);
606

607
    if (!(interfacedef = virInterfaceDefParseString(defaultInterfaceXML)))
L
Laine Stump 已提交
608
        goto error;
609
    if (!(interfaceobj = virInterfaceAssignDef(&privconn->ifaces, interfacedef))) {
L
Laine Stump 已提交
610 611 612 613 614 615
        virInterfaceDefFree(interfacedef);
        goto error;
    }
    interfaceobj->active = 1;
    virInterfaceObjUnlock(interfaceobj);

616
    if (!(pooldef = virStoragePoolDefParseString(defaultPoolXML)))
C
Cole Robinson 已提交
617 618
        goto error;

619
    if (!(poolobj = virStoragePoolObjAssignDef(&privconn->pools,
C
Cole Robinson 已提交
620 621 622 623
                                               pooldef))) {
        virStoragePoolDefFree(pooldef);
        goto error;
    }
624

625
    if (testStoragePoolObjSetDefaults(poolobj) == -1) {
626
        virStoragePoolObjUnlock(poolobj);
C
Cole Robinson 已提交
627
        goto error;
628
    }
C
Cole Robinson 已提交
629
    poolobj->active = 1;
630
    virStoragePoolObjUnlock(poolobj);
C
Cole Robinson 已提交
631

632
    /* Init default node device */
633
    if (!(nodedef = virNodeDeviceDefParseString(defaultNodeXML, 0, NULL)))
634
        goto error;
635
    if (!(nodeobj = virNodeDeviceAssignDef(&privconn->devs,
636 637 638 639 640 641
                                           nodedef))) {
        virNodeDeviceDefFree(nodedef);
        goto error;
    }
    virNodeDeviceObjUnlock(nodeobj);

642
    testDriverUnlock(privconn);
643

644 645 646
    return VIR_DRV_OPEN_SUCCESS;

error:
647
    virObjectUnref(privconn->domains);
648
    virNetworkObjListFree(&privconn->networks);
L
Laine Stump 已提交
649
    virInterfaceObjListFree(&privconn->ifaces);
C
Cole Robinson 已提交
650
    virStoragePoolObjListFree(&privconn->pools);
651
    virNodeDeviceObjListFree(&privconn->devs);
652
    virObjectUnref(privconn->caps);
653
    testDriverUnlock(privconn);
654
    conn->privateData = NULL;
655
    VIR_FREE(privconn);
656
    virDomainDefFree(domdef);
657
    return VIR_DRV_OPEN_ERROR;
658 659 660 661
}


static char *testBuildFilename(const char *relativeTo,
662 663 664
                               const char *filename) {
    char *offset;
    int baseLen;
665 666
    char *ret;

667
    if (!filename || filename[0] == '\0')
668
        return NULL;
669 670 671 672
    if (filename[0] == '/') {
        ignore_value(VIR_STRDUP(ret, filename));
        return ret;
    }
673

674
    offset = strrchr(relativeTo, '/');
675
    if ((baseLen = (offset-relativeTo+1))) {
676
        char *absFile;
C
Chris Lalancette 已提交
677 678
        int totalLen = baseLen + strlen(filename) + 1;
        if (VIR_ALLOC_N(absFile, totalLen) < 0)
679
            return NULL;
C
Chris Lalancette 已提交
680 681 682 683
        if (virStrncpy(absFile, relativeTo, baseLen, totalLen) == NULL) {
            VIR_FREE(absFile);
            return NULL;
        }
684 685 686
        strcat(absFile, filename);
        return absFile;
    } else {
687 688
        ignore_value(VIR_STRDUP(ret, filename));
        return ret;
689
    }
690 691
}

692 693 694
static int
testParseNodeInfo(virNodeInfoPtr nodeInfo, xmlXPathContextPtr ctxt)
{
695
    char *str;
696 697
    long l;
    int ret;
698

699
    ret = virXPathLong("string(/node/cpu/nodes[1])", ctxt, &l);
700 701 702
    if (ret == 0) {
        nodeInfo->nodes = l;
    } else if (ret == -2) {
703 704
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu nodes value"));
705
        goto error;
706
    }
707

708
    ret = virXPathLong("string(/node/cpu/sockets[1])", ctxt, &l);
709 710 711
    if (ret == 0) {
        nodeInfo->sockets = l;
    } else if (ret == -2) {
712 713
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu sockets value"));
714
        goto error;
715
    }
716

717
    ret = virXPathLong("string(/node/cpu/cores[1])", ctxt, &l);
718 719 720
    if (ret == 0) {
        nodeInfo->cores = l;
    } else if (ret == -2) {
721 722
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu cores value"));
723
        goto error;
724 725
    }

726
    ret = virXPathLong("string(/node/cpu/threads[1])", ctxt, &l);
727 728 729
    if (ret == 0) {
        nodeInfo->threads = l;
    } else if (ret == -2) {
730 731
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu threads value"));
732
        goto error;
733
    }
734

735 736
    nodeInfo->cpus = (nodeInfo->cores * nodeInfo->threads *
                      nodeInfo->sockets * nodeInfo->nodes);
737
    ret = virXPathLong("string(/node/cpu/active[1])", ctxt, &l);
738 739
    if (ret == 0) {
        if (l < nodeInfo->cpus) {
740 741
            nodeInfo->cpus = l;
        }
742
    } else if (ret == -2) {
743 744
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu active value"));
745
        goto error;
746
    }
747
    ret = virXPathLong("string(/node/cpu/mhz[1])", ctxt, &l);
748 749 750
    if (ret == 0) {
        nodeInfo->mhz = l;
    } else if (ret == -2) {
751 752
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu mhz value"));
753
        goto error;
754 755
    }

756
    str = virXPathString("string(/node/cpu/model[1])", ctxt);
757
    if (str != NULL) {
C
Chris Lalancette 已提交
758
        if (virStrcpyStatic(nodeInfo->model, str) == NULL) {
759 760
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Model %s too big for destination"), str);
C
Chris Lalancette 已提交
761 762 763
            VIR_FREE(str);
            goto error;
        }
764
        VIR_FREE(str);
765 766
    }

767
    ret = virXPathLong("string(/node/memory[1])", ctxt, &l);
768 769 770
    if (ret == 0) {
        nodeInfo->memory = l;
    } else if (ret == -2) {
771 772
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node memory value"));
773
        goto error;
774
    }
775

776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792
    return 0;
error:
    return -1;
}

static int
testParseDomains(virConnectPtr conn,
                 testConnPtr privconn, const char *file,
                 xmlDocPtr doc, xmlXPathContextPtr ctxt)
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virDomainObjPtr obj;

    num = virXPathNodeSet("/node/domain", ctxt, &nodes);
    if (num < 0) {
793
        goto error;
794
    }
795

796
    for (i = 0; i < num; i++) {
797
        virDomainDefPtr def;
798
        char *relFile = virXMLPropString(nodes[i], "file");
799 800 801 802
        if (relFile != NULL) {
            char *absFile = testBuildFilename(file, relFile);
            VIR_FREE(relFile);
            if (!absFile) {
803 804
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("resolving domain filename"));
805 806
                goto error;
            }
807 808
            def = virDomainDefParseFile(absFile, privconn->caps,
                                        privconn->xmlopt,
M
Matthias Bolte 已提交
809
                                        1 << VIR_DOMAIN_VIRT_TEST,
810
                                        VIR_DOMAIN_XML_INACTIVE);
811
            VIR_FREE(absFile);
812 813 814
            if (!def)
                goto error;
        } else {
815
            if ((def = virDomainDefParseNode(doc, nodes[i],
816
                                             privconn->caps, privconn->xmlopt,
M
Matthias Bolte 已提交
817
                                             1 << VIR_DOMAIN_VIRT_TEST,
818
                                             VIR_DOMAIN_XML_INACTIVE)) == NULL)
819 820 821
                goto error;
        }

822
        if (testDomainGenerateIfnames(def) < 0 ||
823
            !(obj = virDomainObjListAdd(privconn->domains,
824
                                        def,
825
                                        privconn->xmlopt,
826
                                        0, NULL))) {
827
            virDomainDefFree(def);
828 829
            goto error;
        }
830

831 832 833
        obj->persistent = 1;
        if (testDomainStartState(conn, obj, VIR_DOMAIN_RUNNING_BOOTED) < 0) {
            virObjectUnlock(obj);
834 835 836
            goto error;
        }

837
        virObjectUnlock(obj);
838
    }
839

840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856
    ret = 0;
error:
    VIR_FREE(nodes);
    return ret;
}

static int
testParseNetworks(testConnPtr privconn, const char *file,
                  xmlDocPtr doc, xmlXPathContextPtr ctxt)
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virNetworkObjPtr obj;

    num = virXPathNodeSet("/node/network", ctxt, &nodes);
    if (num < 0) {
857 858
        goto error;
    }
859 860

    for (i = 0; i < num; i++) {
861
        virNetworkDefPtr def;
862
        char *relFile = virXMLPropString(nodes[i], "file");
863 864 865
        if (relFile != NULL) {
            char *absFile = testBuildFilename(file, relFile);
            VIR_FREE(relFile);
866
            if (!absFile) {
867 868
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("resolving network filename"));
869 870
                goto error;
            }
871

872
            def = virNetworkDefParseFile(absFile);
873
            VIR_FREE(absFile);
874 875 876
            if (!def)
                goto error;
        } else {
877
            if ((def = virNetworkDefParseNode(doc, nodes[i])) == NULL)
878
                goto error;
879
        }
880 881

        if (!(obj = virNetworkAssignDef(&privconn->networks, def, false))) {
882 883
            virNetworkDefFree(def);
            goto error;
884
        }
885 886 887 888

        obj->persistent = 1;
        obj->active = 1;
        virNetworkObjUnlock(obj);
889
    }
890

891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907
    ret = 0;
error:
    VIR_FREE(nodes);
    return ret;
}

static int
testParseInterfaces(testConnPtr privconn, const char *file,
                    xmlDocPtr doc, xmlXPathContextPtr ctxt)
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virInterfaceObjPtr obj;

    num = virXPathNodeSet("/node/interface", ctxt, &nodes);
    if (num < 0) {
L
Laine Stump 已提交
908 909
        goto error;
    }
910 911

    for (i = 0; i < num; i++) {
L
Laine Stump 已提交
912
        virInterfaceDefPtr def;
913
        char *relFile = virXMLPropString(nodes[i], "file");
L
Laine Stump 已提交
914 915 916 917
        if (relFile != NULL) {
            char *absFile = testBuildFilename(file, relFile);
            VIR_FREE(relFile);
            if (!absFile) {
918 919
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("resolving interface filename"));
L
Laine Stump 已提交
920 921 922
                goto error;
            }

923
            def = virInterfaceDefParseFile(absFile);
L
Laine Stump 已提交
924 925 926 927
            VIR_FREE(absFile);
            if (!def)
                goto error;
        } else {
928
            if ((def = virInterfaceDefParseNode(doc, nodes[i])) == NULL)
L
Laine Stump 已提交
929 930
                goto error;
        }
931

932
        if (!(obj = virInterfaceAssignDef(&privconn->ifaces, def))) {
L
Laine Stump 已提交
933 934 935
            virInterfaceDefFree(def);
            goto error;
        }
936

937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011
        obj->active = 1;
        virInterfaceObjUnlock(obj);
    }

    ret = 0;
error:
    VIR_FREE(nodes);
    return ret;
}

static int
testOpenVolumesForPool(xmlDocPtr xml,
                       xmlXPathContextPtr ctxt,
                       const char *file,
                       virStoragePoolObjPtr pool,
                       int poolidx)
{
    char *vol_xpath;
    size_t i;
    int num, ret = -1;
    xmlNodePtr *nodes = NULL;
    virStorageVolDefPtr def = NULL;

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

    num = virXPathNodeSet(vol_xpath, ctxt, &nodes);
    VIR_FREE(vol_xpath);
    if (num < 0) {
        goto error;
    }

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

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

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

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

        if (!def->key && VIR_STRDUP(def->key, def->target.path) < 0)
            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;
L
Laine Stump 已提交
1012 1013
    }

1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031
    ret = 0;
error:
    virStorageVolDefFree(def);
    VIR_FREE(nodes);
    return ret;
}

static int
testParseStorage(testConnPtr privconn, const char *file,
                 xmlDocPtr doc, xmlXPathContextPtr ctxt)
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virStoragePoolObjPtr obj;

    num = virXPathNodeSet("/node/pool", ctxt, &nodes);
    if (num < 0) {
C
Cole Robinson 已提交
1032 1033
        goto error;
    }
1034 1035

    for (i = 0; i < num; i++) {
C
Cole Robinson 已提交
1036
        virStoragePoolDefPtr def;
1037
        char *relFile = virXMLPropString(nodes[i], "file");
C
Cole Robinson 已提交
1038 1039 1040 1041
        if (relFile != NULL) {
            char *absFile = testBuildFilename(file, relFile);
            VIR_FREE(relFile);
            if (!absFile) {
1042 1043
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("resolving pool filename"));
C
Cole Robinson 已提交
1044 1045 1046
                goto error;
            }

1047
            def = virStoragePoolDefParseFile(absFile);
C
Cole Robinson 已提交
1048 1049 1050 1051
            VIR_FREE(absFile);
            if (!def)
                goto error;
        } else {
1052 1053
            if ((def = virStoragePoolDefParseNode(doc,
                                                  nodes[i])) == NULL) {
C
Cole Robinson 已提交
1054 1055 1056 1057
                goto error;
            }
        }

1058
        if (!(obj = virStoragePoolObjAssignDef(&privconn->pools,
C
Cole Robinson 已提交
1059 1060 1061 1062 1063
                                                def))) {
            virStoragePoolDefFree(def);
            goto error;
        }

1064 1065
        if (testStoragePoolObjSetDefaults(obj) == -1) {
            virStoragePoolObjUnlock(obj);
C
Cole Robinson 已提交
1066
            goto error;
1067
        }
1068
        obj->active = 1;
1069 1070

        /* Find storage volumes */
1071 1072
        if (testOpenVolumesForPool(doc, ctxt, file, obj, i+1) < 0) {
            virStoragePoolObjUnlock(obj);
1073 1074 1075
            goto error;
        }

1076
        virStoragePoolObjUnlock(obj);
C
Cole Robinson 已提交
1077 1078
    }

1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
    ret = 0;
error:
    VIR_FREE(nodes);
    return ret;
}

static int
testParseNodedevs(testConnPtr privconn, const char *file,
                  xmlDocPtr doc, xmlXPathContextPtr ctxt)
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virNodeDeviceObjPtr obj;

    num = virXPathNodeSet("/node/device", ctxt, &nodes);
    if (num < 0) {
1096 1097
        goto error;
    }
1098 1099

    for (i = 0; i < num; i++) {
1100
        virNodeDeviceDefPtr def;
1101
        char *relFile = virXMLPropString(nodes[i], "file");
1102 1103 1104 1105 1106 1107

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

            if (!absFile) {
1108 1109
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("resolving device filename"));
1110 1111 1112
                goto error;
            }

1113
            def = virNodeDeviceDefParseFile(absFile, 0, NULL);
1114 1115 1116 1117
            VIR_FREE(absFile);
            if (!def)
                goto error;
        } else {
1118 1119
            if ((def = virNodeDeviceDefParseNode(doc,
                                                 nodes[i], 0, NULL)) == NULL)
1120 1121
                goto error;
        }
1122 1123

        if (!(obj = virNodeDeviceAssignDef(&privconn->devs, def))) {
1124 1125 1126
            virNodeDeviceDefFree(def);
            goto error;
        }
1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150

        virNodeDeviceObjUnlock(obj);
    }

    ret = 0;
error:
    VIR_FREE(nodes);
    return ret;
}

static int
testOpenFromFile(virConnectPtr conn, const char *file)
{
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
    testConnPtr privconn;

    if (VIR_ALLOC(privconn) < 0)
        return VIR_DRV_OPEN_ERROR;
    if (virMutexInit(&privconn->lock) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot initialize mutex"));
        VIR_FREE(privconn);
        return VIR_DRV_OPEN_ERROR;
1151 1152
    }

1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192
    testDriverLock(privconn);
    conn->privateData = privconn;

    if (!(privconn->domains = virDomainObjListNew()))
        goto error;

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

    if (!(privconn->xmlopt = testBuildXMLConfig()))
        goto error;

    if (!(doc = virXMLParseFileCtxt(file, &ctxt))) {
        goto error;
    }

    if (!xmlStrEqual(ctxt->node->name, BAD_CAST "node")) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("Root element is not 'node'"));
        goto error;
    }

    privconn->nextDomID = 1;
    privconn->numCells = 0;
    if (VIR_STRDUP(privconn->path, file) < 0)
        goto error;
    memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));

    if (testParseNodeInfo(&privconn->nodeInfo, ctxt) < 0)
        goto error;
    if (testParseDomains(conn, privconn, file, doc, ctxt) < 0)
        goto error;
    if (testParseNetworks(privconn, file, doc, ctxt) < 0)
        goto error;
    if (testParseInterfaces(privconn, file, doc, ctxt) < 0)
        goto error;
    if (testParseStorage(privconn, file, doc, ctxt) < 0)
        goto error;
    if (testParseNodedevs(privconn, file, doc, ctxt) < 0)
        goto error;
1193

J
Jim Meyering 已提交
1194
    xmlXPathFreeContext(ctxt);
1195
    xmlFreeDoc(doc);
1196
    testDriverUnlock(privconn);
1197

1198
    return 0;
1199 1200

 error:
J
Jim Meyering 已提交
1201
    xmlXPathFreeContext(ctxt);
1202
    xmlFreeDoc(doc);
1203
    virObjectUnref(privconn->domains);
1204
    virNetworkObjListFree(&privconn->networks);
L
Laine Stump 已提交
1205
    virInterfaceObjListFree(&privconn->ifaces);
C
Cole Robinson 已提交
1206
    virStoragePoolObjListFree(&privconn->pools);
E
Eric Blake 已提交
1207
    VIR_FREE(privconn->path);
1208
    testDriverUnlock(privconn);
1209
    VIR_FREE(privconn);
1210
    conn->privateData = NULL;
1211
    return VIR_DRV_OPEN_ERROR;
1212 1213
}

1214

1215 1216 1217
static virDrvOpenStatus testConnectOpen(virConnectPtr conn,
                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                        unsigned int flags)
1218
{
1219
    int ret;
1220
    testConnPtr privconn;
1221

E
Eric Blake 已提交
1222 1223
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

1224
    if (!conn->uri)
1225
        return VIR_DRV_OPEN_DECLINED;
1226

1227
    if (!conn->uri->scheme || STRNEQ(conn->uri->scheme, "test"))
1228
        return VIR_DRV_OPEN_DECLINED;
1229

1230
    /* Remote driver should handle these. */
1231
    if (conn->uri->server)
1232 1233
        return VIR_DRV_OPEN_DECLINED;

1234
    /* From this point on, the connection is for us. */
1235 1236 1237
    if (!conn->uri->path
        || conn->uri->path[0] == '\0'
        || (conn->uri->path[0] == '/' && conn->uri->path[1] == '\0')) {
1238 1239
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("testOpen: supply a path or use test:///default"));
1240 1241
        return VIR_DRV_OPEN_ERROR;
    }
1242

1243
    if (STREQ(conn->uri->path, "/default"))
1244 1245
        ret = testOpenDefault(conn);
    else
1246
        ret = testOpenFromFile(conn,
1247
                               conn->uri->path);
1248

1249 1250 1251 1252 1253
    if (ret != VIR_DRV_OPEN_SUCCESS)
        return ret;

    privconn = conn->privateData;
    testDriverLock(privconn);
1254

1255
    privconn->domainEventState = virDomainEventStateNew();
1256
    if (!privconn->domainEventState) {
1257
        testDriverUnlock(privconn);
1258
        testConnectClose(conn);
1259
        return VIR_DRV_OPEN_ERROR;
1260 1261
    }

1262 1263 1264
    testDriverUnlock(privconn);

    return VIR_DRV_OPEN_SUCCESS;
1265 1266
}

1267
static int testConnectClose(virConnectPtr conn)
1268
{
1269
    testConnPtr privconn = conn->privateData;
1270
    testDriverLock(privconn);
1271
    virObjectUnref(privconn->caps);
1272
    virObjectUnref(privconn->xmlopt);
1273
    virObjectUnref(privconn->domains);
D
Daniel P. Berrange 已提交
1274
    virNodeDeviceObjListFree(&privconn->devs);
1275
    virNetworkObjListFree(&privconn->networks);
L
Laine Stump 已提交
1276
    virInterfaceObjListFree(&privconn->ifaces);
C
Cole Robinson 已提交
1277
    virStoragePoolObjListFree(&privconn->pools);
1278
    virDomainEventStateFree(privconn->domainEventState);
E
Eric Blake 已提交
1279
    VIR_FREE(privconn->path);
1280

1281
    testDriverUnlock(privconn);
1282
    virMutexDestroy(&privconn->lock);
1283

1284
    VIR_FREE(privconn);
1285
    conn->privateData = NULL;
1286
    return 0;
1287 1288
}

1289 1290
static int testConnectGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
                                 unsigned long *hvVer)
1291
{
1292
    *hvVer = 2;
1293
    return 0;
1294 1295
}

1296 1297 1298 1299 1300 1301
static char *testConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return virGetHostname();
}


1302
static int testConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
1303 1304 1305 1306
{
    return 1;
}

1307
static int testConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
1308 1309 1310 1311
{
    return 0;
}

1312
static int testConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
1313 1314 1315 1316
{
    return 1;
}

1317 1318
static int testConnectGetMaxVcpus(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type ATTRIBUTE_UNUSED)
1319 1320 1321 1322 1323 1324
{
    return 32;
}

static int testNodeGetInfo(virConnectPtr conn,
                           virNodeInfoPtr info)
1325
{
1326
    testConnPtr privconn = conn->privateData;
1327
    testDriverLock(privconn);
1328
    memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo));
1329
    testDriverUnlock(privconn);
1330
    return 0;
1331 1332
}

1333
static char *testConnectGetCapabilities(virConnectPtr conn)
1334
{
1335
    testConnPtr privconn = conn->privateData;
1336
    char *xml;
1337
    testDriverLock(privconn);
1338
    if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL)
1339
        virReportOOMError();
1340
    testDriverUnlock(privconn);
1341
    return xml;
1342 1343
}

1344
static int testConnectNumOfDomains(virConnectPtr conn)
1345
{
1346
    testConnPtr privconn = conn->privateData;
1347
    int count;
1348

1349
    testDriverLock(privconn);
1350
    count = virDomainObjListNumOfDomains(privconn->domains, true, NULL, NULL);
1351
    testDriverUnlock(privconn);
1352

1353
    return count;
1354 1355
}

1356 1357 1358 1359 1360 1361 1362
static int testDomainIsActive(virDomainPtr dom)
{
    testConnPtr privconn = dom->conn->privateData;
    virDomainObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
1363
    obj = virDomainObjListFindByUUID(privconn->domains, dom->uuid);
1364 1365
    testDriverUnlock(privconn);
    if (!obj) {
1366
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1367 1368 1369 1370 1371 1372
        goto cleanup;
    }
    ret = virDomainObjIsActive(obj);

cleanup:
    if (obj)
1373
        virObjectUnlock(obj);
1374 1375 1376 1377 1378 1379 1380 1381 1382 1383
    return ret;
}

static int testDomainIsPersistent(virDomainPtr dom)
{
    testConnPtr privconn = dom->conn->privateData;
    virDomainObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
1384
    obj = virDomainObjListFindByUUID(privconn->domains, dom->uuid);
1385 1386
    testDriverUnlock(privconn);
    if (!obj) {
1387
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1388 1389 1390 1391 1392 1393
        goto cleanup;
    }
    ret = obj->persistent;

cleanup:
    if (obj)
1394
        virObjectUnlock(obj);
1395 1396 1397
    return ret;
}

1398 1399 1400 1401 1402
static int testDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
{
    return 0;
}

1403
static virDomainPtr
1404
testDomainCreateXML(virConnectPtr conn, const char *xml,
1405
                      unsigned int flags)
1406
{
1407
    testConnPtr privconn = conn->privateData;
1408
    virDomainPtr ret = NULL;
1409
    virDomainDefPtr def;
1410
    virDomainObjPtr dom = NULL;
1411
    virDomainEventPtr event = NULL;
1412

1413 1414
    virCheckFlags(0, NULL);

1415
    testDriverLock(privconn);
1416 1417
    if ((def = virDomainDefParseString(xml,privconn->caps, privconn->xmlopt,
                                       1 << VIR_DOMAIN_VIRT_TEST,
1418
                                       VIR_DOMAIN_XML_INACTIVE)) == NULL)
1419
        goto cleanup;
1420

1421
    if (testDomainGenerateIfnames(def) < 0)
1422
        goto cleanup;
1423
    if (!(dom = virDomainObjListAdd(privconn->domains,
1424
                                    def,
1425
                                    privconn->xmlopt,
1426 1427
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
1428 1429
        goto cleanup;
    def = NULL;
1430

J
Jiri Denemark 已提交
1431
    if (testDomainStartState(conn, dom, VIR_DOMAIN_RUNNING_BOOTED) < 0)
1432
        goto cleanup;
1433

1434 1435 1436 1437
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);

1438
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1439
    if (ret)
1440
        ret->id = dom->def->id;
1441 1442

cleanup:
1443
    if (dom)
1444
        virObjectUnlock(dom);
1445 1446
    if (event)
        testDomainEventQueue(privconn, event);
1447
    virDomainDefFree(def);
1448
    testDriverUnlock(privconn);
1449
    return ret;
1450 1451 1452
}


1453
static virDomainPtr testDomainLookupByID(virConnectPtr conn,
1454
                                         int id)
1455
{
1456
    testConnPtr privconn = conn->privateData;
1457 1458
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1459

1460
    testDriverLock(privconn);
1461
    dom = virDomainObjListFindByID(privconn->domains, id);
1462 1463 1464
    testDriverUnlock(privconn);

    if (dom == NULL) {
1465
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1466
        goto cleanup;
1467 1468
    }

1469
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1470 1471 1472 1473
    if (ret)
        ret->id = dom->def->id;

cleanup:
1474
    if (dom)
1475
        virObjectUnlock(dom);
1476
    return ret;
1477 1478
}

1479
static virDomainPtr testDomainLookupByUUID(virConnectPtr conn,
1480
                                           const unsigned char *uuid)
1481
{
1482
    testConnPtr privconn = conn->privateData;
1483
    virDomainPtr ret = NULL;
1484
    virDomainObjPtr dom;
1485

1486
    testDriverLock(privconn);
1487
    dom = virDomainObjListFindByUUID(privconn->domains, uuid);
1488 1489 1490
    testDriverUnlock(privconn);

    if (dom == NULL) {
1491
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1492
        goto cleanup;
1493
    }
1494

1495
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1496 1497 1498 1499
    if (ret)
        ret->id = dom->def->id;

cleanup:
1500
    if (dom)
1501
        virObjectUnlock(dom);
1502
    return ret;
1503 1504
}

1505
static virDomainPtr testDomainLookupByName(virConnectPtr conn,
1506
                                           const char *name)
1507
{
1508
    testConnPtr privconn = conn->privateData;
1509 1510
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1511

1512
    testDriverLock(privconn);
1513
    dom = virDomainObjListFindByName(privconn->domains, name);
1514 1515 1516
    testDriverUnlock(privconn);

    if (dom == NULL) {
1517
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1518
        goto cleanup;
1519
    }
1520

1521
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1522 1523 1524 1525
    if (ret)
        ret->id = dom->def->id;

cleanup:
1526
    if (dom)
1527
        virObjectUnlock(dom);
1528
    return ret;
1529 1530
}

1531 1532 1533
static int testConnectListDomains(virConnectPtr conn,
                                  int *ids,
                                  int maxids)
1534
{
1535
    testConnPtr privconn = conn->privateData;
1536
    int n;
1537

1538
    testDriverLock(privconn);
1539
    n = virDomainObjListGetActiveIDs(privconn->domains, ids, maxids, NULL, NULL);
1540
    testDriverUnlock(privconn);
1541

1542
    return n;
1543 1544
}

1545
static int testDomainDestroy(virDomainPtr domain)
1546
{
1547 1548
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1549
    virDomainEventPtr event = NULL;
1550
    int ret = -1;
1551

1552
    testDriverLock(privconn);
1553 1554
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1555 1556

    if (privdom == NULL) {
1557
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1558
        goto cleanup;
1559
    }
1560

J
Jiri Denemark 已提交
1561
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_DESTROYED);
1562 1563 1564
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
1565

1566
    if (!privdom->persistent) {
1567 1568
        virDomainObjListRemove(privconn->domains,
                               privdom);
1569
        privdom = NULL;
1570
    }
1571 1572 1573

    ret = 0;
cleanup:
1574
    if (privdom)
1575
        virObjectUnlock(privdom);
1576 1577
    if (event)
        testDomainEventQueue(privconn, event);
1578
    testDriverUnlock(privconn);
1579
    return ret;
1580 1581
}

1582
static int testDomainResume(virDomainPtr domain)
1583
{
1584 1585
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1586
    virDomainEventPtr event = NULL;
1587
    int ret = -1;
1588

1589
    testDriverLock(privconn);
1590 1591
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1592
    testDriverUnlock(privconn);
1593 1594

    if (privdom == NULL) {
1595
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1596
        goto cleanup;
1597
    }
1598

J
Jiri Denemark 已提交
1599
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_PAUSED) {
1600 1601
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"),
                       domain->name);
1602
        goto cleanup;
1603
    }
1604

J
Jiri Denemark 已提交
1605 1606
    virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                         VIR_DOMAIN_RUNNING_UNPAUSED);
1607 1608 1609
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_RESUMED,
                                     VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
1610 1611 1612
    ret = 0;

cleanup:
1613
    if (privdom)
1614
        virObjectUnlock(privdom);
1615 1616 1617 1618 1619
    if (event) {
        testDriverLock(privconn);
        testDomainEventQueue(privconn, event);
        testDriverUnlock(privconn);
    }
1620
    return ret;
1621 1622
}

1623
static int testDomainSuspend(virDomainPtr domain)
1624
{
1625 1626
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1627
    virDomainEventPtr event = NULL;
1628
    int ret = -1;
J
Jiri Denemark 已提交
1629
    int state;
1630

1631
    testDriverLock(privconn);
1632 1633
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1634
    testDriverUnlock(privconn);
1635 1636

    if (privdom == NULL) {
1637
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1638
        goto cleanup;
1639
    }
1640

J
Jiri Denemark 已提交
1641 1642
    state = virDomainObjGetState(privdom, NULL);
    if (state == VIR_DOMAIN_SHUTOFF || state == VIR_DOMAIN_PAUSED) {
1643 1644
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"),
                       domain->name);
1645
        goto cleanup;
1646
    }
1647

J
Jiri Denemark 已提交
1648
    virDomainObjSetState(privdom, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
1649 1650 1651
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_SUSPENDED,
                                     VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
1652 1653 1654
    ret = 0;

cleanup:
1655
    if (privdom)
1656
        virObjectUnlock(privdom);
1657 1658 1659 1660 1661 1662

    if (event) {
        testDriverLock(privconn);
        testDomainEventQueue(privconn, event);
        testDriverUnlock(privconn);
    }
1663
    return ret;
1664 1665
}

1666
static int testDomainShutdownFlags(virDomainPtr domain,
1667
                                   unsigned int flags)
1668
{
1669 1670
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1671
    virDomainEventPtr event = NULL;
1672
    int ret = -1;
1673

1674 1675
    virCheckFlags(0, -1);

1676
    testDriverLock(privconn);
1677 1678
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1679 1680

    if (privdom == NULL) {
1681
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1682
        goto cleanup;
1683
    }
1684

J
Jiri Denemark 已提交
1685
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
1686 1687
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("domain '%s' not running"), domain->name);
1688
        goto cleanup;
1689
    }
1690

J
Jiri Denemark 已提交
1691
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1692 1693 1694
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1695

1696
    if (!privdom->persistent) {
1697 1698
        virDomainObjListRemove(privconn->domains,
                               privdom);
1699 1700
        privdom = NULL;
    }
1701

1702
    ret = 0;
1703
cleanup:
1704
    if (privdom)
1705
        virObjectUnlock(privdom);
1706 1707
    if (event)
        testDomainEventQueue(privconn, event);
1708
    testDriverUnlock(privconn);
1709
    return ret;
1710 1711
}

1712
static int testDomainShutdown(virDomainPtr domain)
1713
{
1714
    return testDomainShutdownFlags(domain, 0);
1715 1716
}

1717
/* Similar behaviour as shutdown */
1718
static int testDomainReboot(virDomainPtr domain,
1719
                            unsigned int action ATTRIBUTE_UNUSED)
1720
{
1721 1722
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1723
    virDomainEventPtr event = NULL;
1724
    int ret = -1;
1725

1726
    testDriverLock(privconn);
1727 1728
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1729 1730

    if (privdom == NULL) {
1731
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1732
        goto cleanup;
1733
    }
1734

J
Jiri Denemark 已提交
1735 1736 1737
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTDOWN,
                         VIR_DOMAIN_SHUTDOWN_USER);

1738 1739
    switch (privdom->def->onReboot) {
    case VIR_DOMAIN_LIFECYCLE_DESTROY:
J
Jiri Denemark 已提交
1740 1741
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1742 1743
        break;

1744
    case VIR_DOMAIN_LIFECYCLE_RESTART:
J
Jiri Denemark 已提交
1745 1746
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
1747 1748
        break;

1749
    case VIR_DOMAIN_LIFECYCLE_PRESERVE:
J
Jiri Denemark 已提交
1750 1751
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1752 1753
        break;

1754
    case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME:
J
Jiri Denemark 已提交
1755 1756
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
1757
        break;
1758

1759
    default:
J
Jiri Denemark 已提交
1760 1761
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1762 1763
        break;
    }
1764

J
Jiri Denemark 已提交
1765 1766
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1767 1768 1769
        event = virDomainEventNewFromObj(privdom,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1770

1771
        if (!privdom->persistent) {
1772 1773
            virDomainObjListRemove(privconn->domains,
                                   privdom);
1774 1775
            privdom = NULL;
        }
1776 1777
    }

1778 1779
    ret = 0;
cleanup:
1780
    if (privdom)
1781
        virObjectUnlock(privdom);
1782 1783
    if (event)
        testDomainEventQueue(privconn, event);
1784
    testDriverUnlock(privconn);
1785
    return ret;
1786 1787
}

1788
static int testDomainGetInfo(virDomainPtr domain,
1789
                             virDomainInfoPtr info)
1790
{
1791
    testConnPtr privconn = domain->conn->privateData;
1792
    struct timeval tv;
1793
    virDomainObjPtr privdom;
1794
    int ret = -1;
1795

1796
    testDriverLock(privconn);
1797 1798
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1799
    testDriverUnlock(privconn);
1800 1801

    if (privdom == NULL) {
1802
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1803
        goto cleanup;
1804
    }
1805 1806

    if (gettimeofday(&tv, NULL) < 0) {
1807 1808
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("getting time of day"));
1809
        goto cleanup;
1810 1811
    }

J
Jiri Denemark 已提交
1812
    info->state = virDomainObjGetState(privdom, NULL);
1813 1814
    info->memory = privdom->def->mem.cur_balloon;
    info->maxMem = privdom->def->mem.max_balloon;
1815 1816
    info->nrVirtCpu = privdom->def->vcpus;
    info->cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
1817 1818 1819
    ret = 0;

cleanup:
1820
    if (privdom)
1821
        virObjectUnlock(privdom);
1822
    return ret;
1823 1824
}

1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837
static int
testDomainGetState(virDomainPtr domain,
                   int *state,
                   int *reason,
                   unsigned int flags)
{
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
    int ret = -1;

    virCheckFlags(0, -1);

    testDriverLock(privconn);
1838 1839
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1840 1841 1842
    testDriverUnlock(privconn);

    if (privdom == NULL) {
1843
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1844 1845 1846
        goto cleanup;
    }

J
Jiri Denemark 已提交
1847
    *state = virDomainObjGetState(privdom, reason);
1848 1849 1850 1851
    ret = 0;

cleanup:
    if (privdom)
1852
        virObjectUnlock(privdom);
1853 1854 1855
    return ret;
}

1856 1857
#define TEST_SAVE_MAGIC "TestGuestMagic"

1858 1859 1860
static int
testDomainSaveFlags(virDomainPtr domain, const char *path,
                    const char *dxml, unsigned int flags)
1861
{
1862
    testConnPtr privconn = domain->conn->privateData;
1863 1864 1865
    char *xml = NULL;
    int fd = -1;
    int len;
1866
    virDomainObjPtr privdom;
1867
    virDomainEventPtr event = NULL;
1868
    int ret = -1;
1869

1870 1871
    virCheckFlags(0, -1);
    if (dxml) {
1872 1873
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1874 1875 1876
        return -1;
    }

1877
    testDriverLock(privconn);
1878 1879
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1880 1881

    if (privdom == NULL) {
1882
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1883
        goto cleanup;
1884
    }
1885

1886
    xml = virDomainDefFormat(privdom->def,
C
Cole Robinson 已提交
1887 1888
                             VIR_DOMAIN_XML_SECURE);

1889
    if (xml == NULL) {
1890
        virReportSystemError(errno,
1891 1892
                             _("saving domain '%s' failed to allocate space for metadata"),
                             domain->name);
1893
        goto cleanup;
1894
    }
1895 1896

    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
1897
        virReportSystemError(errno,
1898 1899
                             _("saving domain '%s' to '%s': open failed"),
                             domain->name, path);
1900
        goto cleanup;
1901
    }
1902
    len = strlen(xml);
1903
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
1904
        virReportSystemError(errno,
1905 1906
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1907
        goto cleanup;
1908
    }
1909
    if (safewrite(fd, (char*)&len, sizeof(len)) < 0) {
1910
        virReportSystemError(errno,
1911 1912
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1913
        goto cleanup;
1914
    }
1915
    if (safewrite(fd, xml, len) < 0) {
1916
        virReportSystemError(errno,
1917 1918
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1919
        goto cleanup;
1920
    }
1921

1922
    if (VIR_CLOSE(fd) < 0) {
1923
        virReportSystemError(errno,
1924 1925
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1926
        goto cleanup;
1927
    }
1928 1929
    fd = -1;

J
Jiri Denemark 已提交
1930
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SAVED);
1931 1932 1933
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
1934

1935
    if (!privdom->persistent) {
1936 1937
        virDomainObjListRemove(privconn->domains,
                               privdom);
1938
        privdom = NULL;
1939
    }
1940

1941
    ret = 0;
1942 1943 1944 1945 1946 1947 1948
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) {
1949
        VIR_FORCE_CLOSE(fd);
1950 1951
        unlink(path);
    }
1952
    if (privdom)
1953
        virObjectUnlock(privdom);
1954 1955
    if (event)
        testDomainEventQueue(privconn, event);
1956
    testDriverUnlock(privconn);
1957
    return ret;
1958 1959
}

1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971
static int
testDomainSave(virDomainPtr domain,
               const char *path)
{
    return testDomainSaveFlags(domain, path, NULL, 0);
}

static int
testDomainRestoreFlags(virConnectPtr conn,
                       const char *path,
                       const char *dxml,
                       unsigned int flags)
1972
{
1973
    testConnPtr privconn = conn->privateData;
1974
    char *xml = NULL;
1975
    char magic[15];
1976 1977 1978
    int fd = -1;
    int len;
    virDomainDefPtr def = NULL;
1979
    virDomainObjPtr dom = NULL;
1980
    virDomainEventPtr event = NULL;
1981
    int ret = -1;
1982

1983 1984
    virCheckFlags(0, -1);
    if (dxml) {
1985 1986
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1987 1988 1989
        return -1;
    }

1990 1991
    testDriverLock(privconn);

1992
    if ((fd = open(path, O_RDONLY)) < 0) {
1993
        virReportSystemError(errno,
1994 1995
                             _("cannot read domain image '%s'"),
                             path);
1996
        goto cleanup;
1997
    }
1998
    if (saferead(fd, magic, sizeof(magic)) != sizeof(magic)) {
1999
        virReportSystemError(errno,
2000 2001
                             _("incomplete save header in '%s'"),
                             path);
2002
        goto cleanup;
2003
    }
2004
    if (memcmp(magic, TEST_SAVE_MAGIC, sizeof(magic))) {
2005 2006
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("mismatched header magic"));
2007
        goto cleanup;
2008
    }
2009
    if (saferead(fd, (char*)&len, sizeof(len)) != sizeof(len)) {
2010
        virReportSystemError(errno,
2011 2012
                             _("failed to read metadata length in '%s'"),
                             path);
2013
        goto cleanup;
2014 2015
    }
    if (len < 1 || len > 8192) {
2016 2017
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("length of metadata out of range"));
2018
        goto cleanup;
2019
    }
2020
    if (VIR_ALLOC_N(xml, len+1) < 0)
2021
        goto cleanup;
2022
    if (saferead(fd, xml, len) != len) {
2023
        virReportSystemError(errno,
2024
                             _("incomplete metdata in '%s'"), path);
2025
        goto cleanup;
2026 2027
    }
    xml[len] = '\0';
2028

2029 2030
    def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
                                  1 << VIR_DOMAIN_VIRT_TEST,
2031
                                  VIR_DOMAIN_XML_INACTIVE);
2032
    if (!def)
2033
        goto cleanup;
2034

2035
    if (testDomainGenerateIfnames(def) < 0)
2036
        goto cleanup;
2037
    if (!(dom = virDomainObjListAdd(privconn->domains,
2038
                                    def,
2039
                                    privconn->xmlopt,
2040 2041 2042
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
2043 2044
        goto cleanup;
    def = NULL;
2045

J
Jiri Denemark 已提交
2046
    if (testDomainStartState(conn, dom, VIR_DOMAIN_RUNNING_RESTORED) < 0)
2047 2048
        goto cleanup;

2049 2050 2051
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
2052
    ret = 0;
2053 2054 2055 2056

cleanup:
    virDomainDefFree(def);
    VIR_FREE(xml);
2057
    VIR_FORCE_CLOSE(fd);
2058
    if (dom)
2059
        virObjectUnlock(dom);
2060 2061
    if (event)
        testDomainEventQueue(privconn, event);
2062
    testDriverUnlock(privconn);
2063
    return ret;
2064 2065
}

2066 2067 2068 2069 2070 2071 2072
static int
testDomainRestore(virConnectPtr conn,
                  const char *path)
{
    return testDomainRestoreFlags(conn, path, NULL, 0);
}

2073 2074
static int testDomainCoreDump(virDomainPtr domain,
                              const char *to,
E
Eric Blake 已提交
2075
                              unsigned int flags)
2076
{
2077
    testConnPtr privconn = domain->conn->privateData;
2078
    int fd = -1;
2079
    virDomainObjPtr privdom;
2080
    virDomainEventPtr event = NULL;
2081
    int ret = -1;
2082

E
Eric Blake 已提交
2083 2084
    virCheckFlags(VIR_DUMP_CRASH, -1);

2085
    testDriverLock(privconn);
2086 2087
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2088 2089

    if (privdom == NULL) {
2090
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2091
        goto cleanup;
2092
    }
2093 2094

    if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
2095
        virReportSystemError(errno,
2096 2097
                             _("domain '%s' coredump: failed to open %s"),
                             domain->name, to);
2098
        goto cleanup;
2099
    }
2100
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
2101
        virReportSystemError(errno,
2102 2103
                             _("domain '%s' coredump: failed to write header to %s"),
                             domain->name, to);
2104
        goto cleanup;
2105
    }
2106
    if (VIR_CLOSE(fd) < 0) {
2107
        virReportSystemError(errno,
2108 2109
                             _("domain '%s' coredump: write failed: %s"),
                             domain->name, to);
2110
        goto cleanup;
2111
    }
2112

2113
    if (flags & VIR_DUMP_CRASH) {
J
Jiri Denemark 已提交
2114
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_CRASHED);
2115 2116 2117 2118
        event = virDomainEventNewFromObj(privdom,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
        if (!privdom->persistent) {
2119 2120
            virDomainObjListRemove(privconn->domains,
                                   privdom);
2121 2122
            privdom = NULL;
        }
2123
    }
2124

2125
    ret = 0;
2126
cleanup:
2127
    VIR_FORCE_CLOSE(fd);
2128
    if (privdom)
2129
        virObjectUnlock(privdom);
2130 2131
    if (event)
        testDomainEventQueue(privconn, event);
2132
    testDriverUnlock(privconn);
2133
    return ret;
2134 2135
}

2136
static char *testDomainGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) {
2137 2138 2139
    char *ret;

    ignore_value(VIR_STRDUP(ret, "linux"));
2140
    return ret;
2141 2142
}

2143
static unsigned long long testDomainGetMaxMemory(virDomainPtr domain) {
2144 2145
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2146
    unsigned long long ret = 0;
2147

2148
    testDriverLock(privconn);
2149 2150
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2151
    testDriverUnlock(privconn);
2152 2153

    if (privdom == NULL) {
2154
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2155
        goto cleanup;
2156
    }
2157

2158
    ret = privdom->def->mem.max_balloon;
2159 2160

cleanup:
2161
    if (privdom)
2162
        virObjectUnlock(privdom);
2163
    return ret;
2164 2165
}

2166 2167
static int testDomainSetMaxMemory(virDomainPtr domain,
                                  unsigned long memory)
2168
{
2169 2170
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2171
    int ret = -1;
2172

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

    if (privdom == NULL) {
2179
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2180
        goto cleanup;
2181
    }
2182 2183

    /* XXX validate not over host memory wrt to other domains */
2184
    privdom->def->mem.max_balloon = memory;
2185 2186 2187
    ret = 0;

cleanup:
2188
    if (privdom)
2189
        virObjectUnlock(privdom);
2190
    return ret;
2191 2192
}

2193 2194
static int testDomainSetMemory(virDomainPtr domain,
                               unsigned long memory)
2195
{
2196 2197
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2198
    int ret = -1;
2199

2200
    testDriverLock(privconn);
2201 2202
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2203
    testDriverUnlock(privconn);
2204 2205

    if (privdom == NULL) {
2206
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2207
        goto cleanup;
2208
    }
2209

2210
    if (memory > privdom->def->mem.max_balloon) {
2211
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2212
        goto cleanup;
2213
    }
2214

2215
    privdom->def->mem.cur_balloon = memory;
2216 2217 2218
    ret = 0;

cleanup:
2219
    if (privdom)
2220
        virObjectUnlock(privdom);
2221
    return ret;
2222 2223
}

2224 2225
static int
testDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
C
Cole Robinson 已提交
2226
{
2227 2228 2229 2230 2231
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr vm;
    virDomainDefPtr def;
    int ret = -1;

2232 2233
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2234 2235 2236
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

    testDriverLock(privconn);
2237
    vm = virDomainObjListFindByUUID(privconn->domains, domain->uuid);
2238 2239 2240 2241 2242
    testDriverUnlock(privconn);

    if (!vm) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(domain->uuid, uuidstr);
2243 2244
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching uuid '%s'"), uuidstr);
2245 2246 2247
        goto cleanup;
    }

2248
    if (virDomainLiveConfigHelperMethod(privconn->caps, privconn->xmlopt,
2249
                                        vm, &flags, &def) < 0)
2250
        goto cleanup;
2251

2252
    if (flags & VIR_DOMAIN_AFFECT_LIVE)
2253 2254 2255 2256 2257 2258
        def = vm->def;

    ret = (flags & VIR_DOMAIN_VCPU_MAXIMUM) ? def->maxvcpus : def->vcpus;

cleanup:
    if (vm)
2259
        virObjectUnlock(vm);
2260
    return ret;
C
Cole Robinson 已提交
2261 2262
}

2263 2264 2265
static int
testDomainGetMaxVcpus(virDomainPtr domain)
{
2266
    return testDomainGetVcpusFlags(domain, (VIR_DOMAIN_AFFECT_LIVE |
2267 2268 2269 2270 2271 2272 2273
                                            VIR_DOMAIN_VCPU_MAXIMUM));
}

static int
testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
                        unsigned int flags)
{
2274
    testConnPtr privconn = domain->conn->privateData;
2275
    virDomainObjPtr privdom = NULL;
2276
    virDomainDefPtr persistentDef;
C
Cole Robinson 已提交
2277 2278
    int ret = -1, maxvcpus;

2279 2280
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2281 2282 2283 2284
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

    /* At least one of LIVE or CONFIG must be set.  MAXIMUM cannot be
     * mixed with LIVE.  */
2285 2286 2287
    if ((flags & (VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG)) == 0 ||
        (flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_AFFECT_LIVE)) ==
         (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_AFFECT_LIVE)) {
2288 2289
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
2290 2291
        return -1;
    }
2292
    if (!nrCpus || (maxvcpus = testConnectGetMaxVcpus(domain->conn, NULL)) < nrCpus) {
2293 2294
        virReportError(VIR_ERR_INVALID_ARG,
                       _("argument out of range: %d"), nrCpus);
2295 2296
        return -1;
    }
2297

2298
    testDriverLock(privconn);
2299
    privdom = virDomainObjListFindByUUID(privconn->domains, domain->uuid);
2300 2301 2302
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2303
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2304
        goto cleanup;
2305
    }
2306

2307
    if (!virDomainObjIsActive(privdom) && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
2308 2309
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot hotplug vcpus for an inactive domain"));
C
Cole Robinson 已提交
2310 2311 2312
        goto cleanup;
    }

2313 2314
    /* We allow more cpus in guest than host, but not more than the
     * domain's starting limit.  */
C
Cole Robinson 已提交
2315 2316
    if (!(flags & (VIR_DOMAIN_VCPU_MAXIMUM)) &&
        privdom->def->maxvcpus < maxvcpus)
2317
        maxvcpus = privdom->def->maxvcpus;
C
Cole Robinson 已提交
2318

C
Cole Robinson 已提交
2319
    if (nrCpus > maxvcpus) {
2320 2321 2322
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested cpu amount exceeds maximum (%d > %d)"),
                       nrCpus, maxvcpus);
2323
        goto cleanup;
2324
    }
2325

2326
    if (!(persistentDef = virDomainObjGetPersistentDef(privconn->caps,
2327
                                                       privconn->xmlopt,
2328 2329 2330
                                                       privdom)))
        goto cleanup;

2331
    switch (flags) {
2332
    case VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_AFFECT_CONFIG:
2333 2334 2335
        persistentDef->maxvcpus = nrCpus;
        if (nrCpus < persistentDef->vcpus)
            persistentDef->vcpus = nrCpus;
2336 2337
        ret = 0;
        break;
2338

2339
    case VIR_DOMAIN_AFFECT_CONFIG:
2340
        persistentDef->vcpus = nrCpus;
2341 2342 2343
        ret = 0;
        break;

2344
    case VIR_DOMAIN_AFFECT_LIVE:
2345 2346 2347
        ret = testDomainUpdateVCPUs(domain->conn, privdom, nrCpus, 0);
        break;

2348
    case VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG:
2349
        ret = testDomainUpdateVCPUs(domain->conn, privdom, nrCpus, 0);
2350 2351 2352
        if (ret == 0) {
            persistentDef->vcpus = nrCpus;
        }
2353 2354
        break;
    }
2355 2356

cleanup:
2357
    if (privdom)
2358
        virObjectUnlock(privdom);
2359
    return ret;
2360 2361
}

2362
static int
2363
testDomainSetVcpus(virDomainPtr domain, unsigned int nrCpus)
2364
{
2365
    return testDomainSetVcpusFlags(domain, nrCpus, VIR_DOMAIN_AFFECT_LIVE);
2366 2367
}

C
Cole Robinson 已提交
2368 2369 2370 2371 2372 2373 2374 2375 2376
static int testDomainGetVcpus(virDomainPtr domain,
                              virVcpuInfoPtr info,
                              int maxinfo,
                              unsigned char *cpumaps,
                              int maplen)
{
    testConnPtr privconn = domain->conn->privateData;
    testDomainObjPrivatePtr privdomdata;
    virDomainObjPtr privdom;
2377 2378
    size_t i;
    int v, maxcpu, hostcpus;
C
Cole Robinson 已提交
2379 2380 2381 2382 2383
    int ret = -1;
    struct timeval tv;
    unsigned long long statbase;

    testDriverLock(privconn);
2384
    privdom = virDomainObjListFindByName(privconn->domains, domain->name);
C
Cole Robinson 已提交
2385 2386 2387
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2388
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
C
Cole Robinson 已提交
2389 2390 2391 2392
        goto cleanup;
    }

    if (!virDomainObjIsActive(privdom)) {
2393 2394
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s",_("cannot list vcpus for an inactive domain"));
C
Cole Robinson 已提交
2395 2396 2397 2398 2399 2400
        goto cleanup;
    }

    privdomdata = privdom->privateData;

    if (gettimeofday(&tv, NULL) < 0) {
2401
        virReportSystemError(errno,
C
Cole Robinson 已提交
2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421
                             "%s", _("getting time of day"));
        goto cleanup;
    }

    statbase = (tv.tv_sec * 1000UL * 1000UL) + tv.tv_usec;


    hostcpus = VIR_NODEINFO_MAXCPUS(privconn->nodeInfo);
    maxcpu = maplen * 8;
    if (maxcpu > hostcpus)
        maxcpu = hostcpus;

    /* Clamp to actual number of vcpus */
    if (maxinfo > privdom->def->vcpus)
        maxinfo = privdom->def->vcpus;

    /* Populate virVcpuInfo structures */
    if (info != NULL) {
        memset(info, 0, sizeof(*info) * maxinfo);

2422
        for (i = 0; i < maxinfo; i++) {
C
Cole Robinson 已提交
2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438
            virVcpuInfo privinfo = privdomdata->vcpu_infos[i];

            info[i].number = privinfo.number;
            info[i].state = privinfo.state;
            info[i].cpu = privinfo.cpu;

            /* Fake an increasing cpu time value */
            info[i].cpuTime = statbase / 10;
        }
    }

    /* Populate cpumaps */
    if (cpumaps != NULL) {
        int privmaplen = VIR_CPU_MAPLEN(hostcpus);
        memset(cpumaps, 0, maplen * maxinfo);

2439
        for (v = 0; v < maxinfo; v++) {
C
Cole Robinson 已提交
2440 2441
            unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v);

2442
            for (i = 0; i < maxcpu; i++) {
C
Cole Robinson 已提交
2443 2444 2445 2446 2447 2448 2449 2450 2451 2452
                if (VIR_CPU_USABLE(privdomdata->cpumaps, privmaplen, v, i)) {
                    VIR_USE_CPU(cpumap, i);
                }
            }
        }
    }

    ret = maxinfo;
cleanup:
    if (privdom)
2453
        virObjectUnlock(privdom);
C
Cole Robinson 已提交
2454 2455 2456
    return ret;
}

C
Cole Robinson 已提交
2457 2458 2459 2460 2461 2462 2463 2464 2465
static int testDomainPinVcpu(virDomainPtr domain,
                             unsigned int vcpu,
                             unsigned char *cpumap,
                             int maplen)
{
    testConnPtr privconn = domain->conn->privateData;
    testDomainObjPrivatePtr privdomdata;
    virDomainObjPtr privdom;
    unsigned char *privcpumap;
2466 2467
    size_t i;
    int maxcpu, hostcpus, privmaplen;
C
Cole Robinson 已提交
2468 2469 2470
    int ret = -1;

    testDriverLock(privconn);
2471
    privdom = virDomainObjListFindByName(privconn->domains, domain->name);
C
Cole Robinson 已提交
2472 2473 2474
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2475
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
C
Cole Robinson 已提交
2476 2477 2478 2479
        goto cleanup;
    }

    if (!virDomainObjIsActive(privdom)) {
2480 2481
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s",_("cannot pin vcpus on an inactive domain"));
C
Cole Robinson 已提交
2482 2483 2484 2485
        goto cleanup;
    }

    if (vcpu > privdom->def->vcpus) {
2486 2487
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("requested vcpu is higher than allocated vcpus"));
C
Cole Robinson 已提交
2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501
        goto cleanup;
    }

    privdomdata = privdom->privateData;
    hostcpus = VIR_NODEINFO_MAXCPUS(privconn->nodeInfo);
    privmaplen = VIR_CPU_MAPLEN(hostcpus);

    maxcpu = maplen * 8;
    if (maxcpu > hostcpus)
        maxcpu = hostcpus;

    privcpumap = VIR_GET_CPUMAP(privdomdata->cpumaps, privmaplen, vcpu);
    memset(privcpumap, 0, privmaplen);

2502
    for (i = 0; i < maxcpu; i++) {
C
Cole Robinson 已提交
2503 2504 2505 2506 2507 2508 2509 2510
        if (VIR_CPU_USABLE(cpumap, maplen, 0, i)) {
            VIR_USE_CPU(privcpumap, i);
        }
    }

    ret = 0;
cleanup:
    if (privdom)
2511
        virObjectUnlock(privdom);
C
Cole Robinson 已提交
2512 2513 2514
    return ret;
}

2515
static char *testDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
2516
{
2517
    testConnPtr privconn = domain->conn->privateData;
2518
    virDomainDefPtr def;
2519
    virDomainObjPtr privdom;
2520 2521
    char *ret = NULL;

2522 2523
    /* Flags checked by virDomainDefFormat */

2524
    testDriverLock(privconn);
2525 2526
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2527 2528 2529
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2530
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2531
        goto cleanup;
2532
    }
2533

2534 2535
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
2536

2537
    ret = virDomainDefFormat(def,
2538 2539 2540
                             flags);

cleanup:
2541
    if (privdom)
2542
        virObjectUnlock(privdom);
2543
    return ret;
2544
}
2545

2546
static int testConnectNumOfDefinedDomains(virConnectPtr conn) {
2547
    testConnPtr privconn = conn->privateData;
2548
    int count;
2549

2550
    testDriverLock(privconn);
2551
    count = virDomainObjListNumOfDomains(privconn->domains, false, NULL, NULL);
2552
    testDriverUnlock(privconn);
2553

2554
    return count;
2555 2556
}

2557 2558 2559
static int testConnectListDefinedDomains(virConnectPtr conn,
                                         char **const names,
                                         int maxnames) {
2560

2561
    testConnPtr privconn = conn->privateData;
2562
    int n;
2563

2564
    testDriverLock(privconn);
2565
    memset(names, 0, sizeof(*names)*maxnames);
2566 2567
    n = virDomainObjListGetInactiveNames(privconn->domains, names, maxnames,
                                         NULL, NULL);
2568
    testDriverUnlock(privconn);
2569

2570
    return n;
2571 2572
}

2573
static virDomainPtr testDomainDefineXML(virConnectPtr conn,
2574
                                        const char *xml) {
2575
    testConnPtr privconn = conn->privateData;
2576
    virDomainPtr ret = NULL;
2577
    virDomainDefPtr def;
2578
    virDomainObjPtr dom = NULL;
2579
    virDomainEventPtr event = NULL;
2580
    virDomainDefPtr oldDef = NULL;
2581

2582
    testDriverLock(privconn);
2583 2584
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
                                       1 << VIR_DOMAIN_VIRT_TEST,
2585
                                       VIR_DOMAIN_XML_INACTIVE)) == NULL)
2586
        goto cleanup;
2587

2588
    if (testDomainGenerateIfnames(def) < 0)
2589
        goto cleanup;
2590
    if (!(dom = virDomainObjListAdd(privconn->domains,
2591
                                    def,
2592
                                    privconn->xmlopt,
2593 2594
                                    0,
                                    &oldDef)))
2595
        goto cleanup;
2596
    def = NULL;
2597
    dom->persistent = 1;
2598

2599 2600
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_DEFINED,
2601
                                     !oldDef ?
2602 2603
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
2604

2605
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
2606
    if (ret)
2607
        ret->id = dom->def->id;
2608 2609 2610

cleanup:
    virDomainDefFree(def);
2611
    virDomainDefFree(oldDef);
2612
    if (dom)
2613
        virObjectUnlock(dom);
2614 2615
    if (event)
        testDomainEventQueue(privconn, event);
2616
    testDriverUnlock(privconn);
2617
    return ret;
2618 2619
}

2620 2621 2622
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
                                      int startCell, int maxCells) {
2623
    testConnPtr privconn = conn->privateData;
2624 2625
    int cell;
    size_t i;
2626
    int ret = -1;
2627

2628
    testDriverLock(privconn);
2629
    if (startCell > privconn->numCells) {
2630 2631
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("Range exceeds available cells"));
2632
        goto cleanup;
2633 2634
    }

2635 2636 2637 2638
    for (cell = startCell, i = 0;
         (cell < privconn->numCells && i < maxCells);
         ++cell, ++i) {
        freemems[i] = privconn->cells[cell].mem;
2639
    }
2640
    ret = i;
2641

2642
cleanup:
2643
    testDriverUnlock(privconn);
2644
    return ret;
2645 2646 2647
}


2648
static int testDomainCreateWithFlags(virDomainPtr domain, unsigned int flags) {
2649 2650
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2651
    virDomainEventPtr event = NULL;
2652
    int ret = -1;
2653

2654 2655
    virCheckFlags(0, -1);

2656
    testDriverLock(privconn);
2657 2658
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2659 2660

    if (privdom == NULL) {
2661
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2662
        goto cleanup;
2663
    }
2664

J
Jiri Denemark 已提交
2665
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_SHUTOFF) {
2666 2667
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Domain '%s' is already running"), domain->name);
2668
        goto cleanup;
2669 2670
    }

J
Jiri Denemark 已提交
2671 2672
    if (testDomainStartState(domain->conn, privdom,
                             VIR_DOMAIN_RUNNING_BOOTED) < 0)
2673 2674 2675
        goto cleanup;
    domain->id = privdom->def->id;

2676 2677 2678
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
2679
    ret = 0;
2680

2681
cleanup:
2682
    if (privdom)
2683
        virObjectUnlock(privdom);
2684 2685
    if (event)
        testDomainEventQueue(privconn, event);
2686
    testDriverUnlock(privconn);
2687
    return ret;
2688 2689
}

2690 2691 2692 2693
static int testDomainCreate(virDomainPtr domain) {
    return testDomainCreateWithFlags(domain, 0);
}

2694 2695 2696
static int testDomainUndefineFlags(virDomainPtr domain,
                                   unsigned int flags)
{
2697 2698
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2699
    virDomainEventPtr event = NULL;
2700
    int ret = -1;
2701

2702 2703
    virCheckFlags(0, -1);

2704
    testDriverLock(privconn);
2705 2706
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2707 2708

    if (privdom == NULL) {
2709
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2710
        goto cleanup;
2711
    }
2712

2713 2714 2715
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
2716 2717
    if (virDomainObjIsActive(privdom)) {
        privdom->persistent = 0;
2718
    } else {
2719 2720
        virDomainObjListRemove(privconn->domains,
                               privdom);
2721 2722 2723
        privdom = NULL;
    }

2724
    ret = 0;
2725

2726
cleanup:
2727
    if (privdom)
2728
        virObjectUnlock(privdom);
2729 2730
    if (event)
        testDomainEventQueue(privconn, event);
2731
    testDriverUnlock(privconn);
2732
    return ret;
2733 2734
}

2735 2736 2737 2738 2739
static int testDomainUndefine(virDomainPtr domain)
{
    return testDomainUndefineFlags(domain, 0);
}

2740 2741 2742
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
2743 2744
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2745
    int ret = -1;
2746

2747
    testDriverLock(privconn);
2748 2749
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2750
    testDriverUnlock(privconn);
2751 2752

    if (privdom == NULL) {
2753
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2754
        goto cleanup;
2755 2756
    }

2757
    *autostart = privdom->autostart;
2758 2759 2760
    ret = 0;

cleanup:
2761
    if (privdom)
2762
        virObjectUnlock(privdom);
2763
    return ret;
2764 2765 2766 2767 2768 2769
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
2770 2771
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2772
    int ret = -1;
2773

2774
    testDriverLock(privconn);
2775 2776
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2777
    testDriverUnlock(privconn);
2778 2779

    if (privdom == NULL) {
2780
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2781
        goto cleanup;
2782 2783
    }

2784
    privdom->autostart = autostart ? 1 : 0;
2785 2786 2787
    ret = 0;

cleanup:
2788
    if (privdom)
2789
        virObjectUnlock(privdom);
2790
    return ret;
2791
}
2792

2793
static char *testDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED,
2794 2795
                                        int *nparams)
{
2796 2797
    char *type = NULL;

2798 2799 2800
    if (nparams)
        *nparams = 1;

2801
    ignore_value(VIR_STRDUP(type, "fair"));
2802

2803 2804 2805
    return type;
}

2806
static int
2807 2808 2809 2810
testDomainGetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int *nparams,
                                      unsigned int flags)
2811
{
2812 2813
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2814
    int ret = -1;
2815

2816 2817
    virCheckFlags(0, -1);

2818
    testDriverLock(privconn);
2819 2820
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2821
    testDriverUnlock(privconn);
2822 2823

    if (privdom == NULL) {
2824
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2825
        goto cleanup;
2826 2827
    }

2828 2829
    if (virTypedParameterAssign(params, VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, 50) < 0)
2830
        goto cleanup;
2831 2832
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
2833 2834

    *nparams = 1;
2835 2836 2837
    ret = 0;

cleanup:
2838
    if (privdom)
2839
        virObjectUnlock(privdom);
2840
    return ret;
2841
}
2842

2843
static int
2844 2845 2846
testDomainGetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int *nparams)
2847
{
2848
    return testDomainGetSchedulerParametersFlags(domain, params, nparams, 0);
2849
}
2850

2851
static int
2852 2853 2854 2855
testDomainSetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int nparams,
                                      unsigned int flags)
2856
{
2857 2858
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2859 2860
    int ret = -1;
    size_t i;
2861

2862
    virCheckFlags(0, -1);
2863 2864 2865 2866
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
2867
        return -1;
2868

2869
    testDriverLock(privconn);
2870 2871
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2872
    testDriverUnlock(privconn);
2873 2874

    if (privdom == NULL) {
2875
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2876
        goto cleanup;
2877 2878
    }

2879
    for (i = 0; i < nparams; i++) {
2880 2881 2882
        if (STREQ(params[i].field, VIR_DOMAIN_SCHEDULER_WEIGHT)) {
            /* XXX */
            /*privdom->weight = params[i].value.ui;*/
2883
        }
2884
    }
2885

2886 2887 2888
    ret = 0;

cleanup:
2889
    if (privdom)
2890
        virObjectUnlock(privdom);
2891
    return ret;
2892 2893
}

2894
static int
2895 2896 2897
testDomainSetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int nparams)
2898
{
2899
    return testDomainSetSchedulerParametersFlags(domain, params, nparams, 0);
2900 2901
}

2902 2903 2904 2905 2906 2907 2908 2909
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;
2910
    int ret = -1;
2911 2912

    testDriverLock(privconn);
2913 2914
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2915 2916 2917
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2918
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2919 2920 2921
        goto error;
    }

2922
    if (virDomainDiskIndexByName(privdom->def, path, false) < 0) {
2923 2924
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path: %s"), path);
2925 2926 2927 2928
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
2929
        virReportSystemError(errno,
2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944
                             "%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)
2945
        virObjectUnlock(privdom);
2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956
    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;
2957 2958
    size_t i;
    int found = 0, ret = -1;
2959 2960

    testDriverLock(privconn);
2961 2962
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2963 2964 2965
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2966
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2967 2968 2969
        goto error;
    }

2970
    for (i = 0; i < privdom->def->nnets; i++) {
2971
        if (privdom->def->nets[i]->ifname &&
2972
            STREQ(privdom->def->nets[i]->ifname, path)) {
2973 2974 2975 2976 2977 2978
            found = 1;
            break;
        }
    }

    if (!found) {
2979 2980
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path, '%s' is not a known interface"), path);
2981 2982 2983 2984
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
2985
        virReportSystemError(errno,
2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003
                             "%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)
3004
        virObjectUnlock(privdom);
3005 3006 3007
    return ret;
}

3008
static virDrvOpenStatus testNetworkOpen(virConnectPtr conn,
3009
                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
3010 3011 3012 3013
                                        unsigned int flags)
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

3014 3015 3016 3017 3018 3019 3020
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

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

3021
static int testNetworkClose(virConnectPtr conn) {
3022 3023 3024 3025 3026
    conn->networkPrivateData = NULL;
    return 0;
}


3027 3028
static virNetworkPtr testNetworkLookupByUUID(virConnectPtr conn,
                                             const unsigned char *uuid)
3029
{
3030 3031
    testConnPtr privconn = conn->privateData;
    virNetworkObjPtr net;
3032
    virNetworkPtr ret = NULL;
3033

3034 3035 3036 3037 3038
    testDriverLock(privconn);
    net = virNetworkFindByUUID(&privconn->networks, uuid);
    testDriverUnlock(privconn);

    if (net == NULL) {
3039
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3040
        goto cleanup;
3041 3042
    }

3043 3044 3045
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

cleanup:
3046 3047
    if (net)
        virNetworkObjUnlock(net);
3048
    return ret;
3049
}
3050

3051
static virNetworkPtr testNetworkLookupByName(virConnectPtr conn,
3052
                                             const char *name)
3053
{
3054
    testConnPtr privconn = conn->privateData;
3055 3056
    virNetworkObjPtr net;
    virNetworkPtr ret = NULL;
3057

3058 3059 3060 3061 3062
    testDriverLock(privconn);
    net = virNetworkFindByName(&privconn->networks, name);
    testDriverUnlock(privconn);

    if (net == NULL) {
3063
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3064
        goto cleanup;
3065 3066
    }

3067 3068 3069
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

cleanup:
3070 3071
    if (net)
        virNetworkObjUnlock(net);
3072
    return ret;
3073 3074 3075
}


3076
static int testConnectNumOfNetworks(virConnectPtr conn) {
3077
    testConnPtr privconn = conn->privateData;
3078 3079
    int numActive = 0;
    size_t i;
3080

3081
    testDriverLock(privconn);
3082
    for (i = 0; i < privconn->networks.count; i++) {
3083
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
3084
        if (virNetworkObjIsActive(privconn->networks.objs[i]))
3085
            numActive++;
3086 3087 3088
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
3089

3090
    return numActive;
3091 3092
}

3093
static int testConnectListNetworks(virConnectPtr conn, char **const names, int nnames) {
3094
    testConnPtr privconn = conn->privateData;
3095 3096
    int n = 0;
    size_t i;
3097

3098
    testDriverLock(privconn);
3099
    memset(names, 0, sizeof(*names)*nnames);
3100
    for (i = 0; i < privconn->networks.count && n < nnames; i++) {
3101
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
3102
        if (virNetworkObjIsActive(privconn->networks.objs[i]) &&
3103
            VIR_STRDUP(names[n++], privconn->networks.objs[i]->def->name) < 0) {
3104
            virNetworkObjUnlock(privconn->networks.objs[i]);
3105
            goto error;
3106 3107 3108 3109
        }
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
3110

3111 3112
    return n;

3113
error:
3114
    for (n = 0; n < nnames; n++)
3115
        VIR_FREE(names[n]);
3116
    testDriverUnlock(privconn);
3117
    return -1;
3118 3119
}

3120
static int testConnectNumOfDefinedNetworks(virConnectPtr conn) {
3121
    testConnPtr privconn = conn->privateData;
3122 3123
    int numInactive = 0;
    size_t i;
3124

3125
    testDriverLock(privconn);
3126
    for (i = 0; i < privconn->networks.count; i++) {
3127
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
3128
        if (!virNetworkObjIsActive(privconn->networks.objs[i]))
3129
            numInactive++;
3130 3131 3132
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
3133

3134
    return numInactive;
3135 3136
}

3137
static int testConnectListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
3138
    testConnPtr privconn = conn->privateData;
3139 3140
    int n = 0;
    size_t i;
3141

3142
    testDriverLock(privconn);
3143
    memset(names, 0, sizeof(*names)*nnames);
3144
    for (i = 0; i < privconn->networks.count && n < nnames; i++) {
3145
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
3146
        if (!virNetworkObjIsActive(privconn->networks.objs[i]) &&
3147
            VIR_STRDUP(names[n++], privconn->networks.objs[i]->def->name) < 0) {
3148
            virNetworkObjUnlock(privconn->networks.objs[i]);
3149
            goto error;
3150 3151 3152 3153
        }
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
3154

3155 3156
    return n;

3157
error:
3158
    for (n = 0; n < nnames; n++)
3159
        VIR_FREE(names[n]);
3160
    testDriverUnlock(privconn);
3161
    return -1;
3162 3163
}

3164
static int
3165
testConnectListAllNetworks(virConnectPtr conn,
3166 3167 3168 3169 3170 3171 3172 3173 3174
                           virNetworkPtr **nets,
                           unsigned int flags)
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

    testDriverLock(privconn);
3175
    ret = virNetworkObjListExport(conn, privconn->networks, nets, NULL, flags);
3176 3177 3178 3179
    testDriverUnlock(privconn);

    return ret;
}
3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190

static int testNetworkIsActive(virNetworkPtr net)
{
    testConnPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virNetworkFindByUUID(&privconn->networks, net->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
3191
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211
        goto cleanup;
    }
    ret = virNetworkObjIsActive(obj);

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

static int testNetworkIsPersistent(virNetworkPtr net)
{
    testConnPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virNetworkFindByUUID(&privconn->networks, net->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
3212
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223
        goto cleanup;
    }
    ret = obj->persistent;

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


3224
static virNetworkPtr testNetworkCreateXML(virConnectPtr conn, const char *xml) {
3225
    testConnPtr privconn = conn->privateData;
3226
    virNetworkDefPtr def;
3227
    virNetworkObjPtr net = NULL;
3228
    virNetworkPtr ret = NULL;
3229

3230
    testDriverLock(privconn);
3231
    if ((def = virNetworkDefParseString(xml)) == NULL)
3232
        goto cleanup;
3233

3234
    if (!(net = virNetworkAssignDef(&privconn->networks, def, false)))
3235 3236
        goto cleanup;
    def = NULL;
3237
    net->active = 1;
3238

3239
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3240

3241 3242
cleanup:
    virNetworkDefFree(def);
3243 3244 3245
    if (net)
        virNetworkObjUnlock(net);
    testDriverUnlock(privconn);
3246
    return ret;
3247 3248
}

3249
static
3250
virNetworkPtr testNetworkDefineXML(virConnectPtr conn, const char *xml)
3251
{
3252
    testConnPtr privconn = conn->privateData;
3253
    virNetworkDefPtr def;
3254
    virNetworkObjPtr net = NULL;
3255
    virNetworkPtr ret = NULL;
3256

3257
    testDriverLock(privconn);
3258
    if ((def = virNetworkDefParseString(xml)) == NULL)
3259
        goto cleanup;
3260

3261
    if (!(net = virNetworkAssignDef(&privconn->networks, def, false)))
3262 3263
        goto cleanup;
    def = NULL;
3264
    net->persistent = 1;
3265

3266
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3267 3268 3269

cleanup:
    virNetworkDefFree(def);
3270 3271 3272
    if (net)
        virNetworkObjUnlock(net);
    testDriverUnlock(privconn);
3273
    return ret;
3274 3275 3276
}

static int testNetworkUndefine(virNetworkPtr network) {
3277 3278
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3279
    int ret = -1;
3280

3281
    testDriverLock(privconn);
3282 3283 3284 3285
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
3286
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3287
        goto cleanup;
3288
    }
3289

D
Daniel P. Berrange 已提交
3290
    if (virNetworkObjIsActive(privnet)) {
3291 3292
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is still running"), network->name);
3293
        goto cleanup;
3294 3295
    }

3296 3297
    virNetworkRemoveInactive(&privconn->networks,
                             privnet);
3298
    privnet = NULL;
3299
    ret = 0;
3300

3301
cleanup:
3302 3303 3304
    if (privnet)
        virNetworkObjUnlock(privnet);
    testDriverUnlock(privconn);
3305
    return ret;
3306 3307
}

3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355
static int
testNetworkUpdate(virNetworkPtr net,
                  unsigned int command,
                  unsigned int section,
                  int parentIndex,
                  const char *xml,
                  unsigned int flags)
{
    testConnPtr privconn = net->conn->privateData;
    virNetworkObjPtr network = NULL;
    int isActive, ret = -1;

    virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
                  VIR_NETWORK_UPDATE_AFFECT_CONFIG,
                  -1);

    testDriverLock(privconn);

    network = virNetworkFindByUUID(&privconn->networks, net->uuid);
    if (!network) {
        virReportError(VIR_ERR_NO_NETWORK,
                       "%s", _("no network with matching uuid"));
        goto cleanup;
    }

    /* VIR_NETWORK_UPDATE_AFFECT_CURRENT means "change LIVE if network
     * is active, else change CONFIG
    */
    isActive = virNetworkObjIsActive(network);
    if ((flags & (VIR_NETWORK_UPDATE_AFFECT_LIVE
                   | VIR_NETWORK_UPDATE_AFFECT_CONFIG)) ==
        VIR_NETWORK_UPDATE_AFFECT_CURRENT) {
        if (isActive)
            flags |= VIR_NETWORK_UPDATE_AFFECT_LIVE;
        else
            flags |= VIR_NETWORK_UPDATE_AFFECT_CONFIG;
    }

    /* update the network config in memory/on disk */
    if (virNetworkObjUpdate(network, command, section, parentIndex, xml, flags) < 0)
       goto cleanup;

    ret = 0;
cleanup:
    testDriverUnlock(privconn);
    return ret;
}

3356
static int testNetworkCreate(virNetworkPtr network) {
3357 3358
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3359
    int ret = -1;
3360

3361
    testDriverLock(privconn);
3362 3363
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
3364
    testDriverUnlock(privconn);
3365 3366

    if (privnet == NULL) {
3367
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3368
        goto cleanup;
3369
    }
3370

D
Daniel P. Berrange 已提交
3371
    if (virNetworkObjIsActive(privnet)) {
3372 3373
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is already running"), network->name);
3374
        goto cleanup;
3375 3376
    }

3377
    privnet->active = 1;
3378
    ret = 0;
3379

3380
cleanup:
3381 3382
    if (privnet)
        virNetworkObjUnlock(privnet);
3383
    return ret;
3384 3385 3386
}

static int testNetworkDestroy(virNetworkPtr network) {
3387 3388
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3389
    int ret = -1;
3390

3391
    testDriverLock(privconn);
3392 3393 3394 3395
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
3396
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3397
        goto cleanup;
3398
    }
3399

3400 3401 3402 3403
    privnet->active = 0;
    if (!privnet->persistent) {
        virNetworkRemoveInactive(&privconn->networks,
                                 privnet);
3404
        privnet = NULL;
3405
    }
3406 3407 3408
    ret = 0;

cleanup:
3409 3410 3411
    if (privnet)
        virNetworkObjUnlock(privnet);
    testDriverUnlock(privconn);
3412
    return ret;
3413 3414
}

3415
static char *testNetworkGetXMLDesc(virNetworkPtr network,
E
Eric Blake 已提交
3416
                                   unsigned int flags)
3417
{
3418 3419
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3420
    char *ret = NULL;
3421

E
Eric Blake 已提交
3422 3423
    virCheckFlags(0, NULL);

3424
    testDriverLock(privconn);
3425 3426
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
3427
    testDriverUnlock(privconn);
3428 3429

    if (privnet == NULL) {
3430
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3431
        goto cleanup;
3432
    }
3433

3434
    ret = virNetworkDefFormat(privnet->def, flags);
3435 3436

cleanup:
3437 3438
    if (privnet)
        virNetworkObjUnlock(privnet);
3439
    return ret;
3440 3441 3442
}

static char *testNetworkGetBridgeName(virNetworkPtr network) {
3443
    testConnPtr privconn = network->conn->privateData;
3444
    char *bridge = NULL;
3445 3446
    virNetworkObjPtr privnet;

3447
    testDriverLock(privconn);
3448 3449
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
3450
    testDriverUnlock(privconn);
3451 3452

    if (privnet == NULL) {
3453
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3454
        goto cleanup;
3455 3456
    }

3457
    if (!(privnet->def->bridge)) {
3458 3459 3460
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("network '%s' does not have a bridge name."),
                       privnet->def->name);
3461 3462 3463
        goto cleanup;
    }

3464
    ignore_value(VIR_STRDUP(bridge, privnet->def->bridge));
3465 3466

cleanup:
3467 3468
    if (privnet)
        virNetworkObjUnlock(privnet);
3469 3470 3471 3472 3473
    return bridge;
}

static int testNetworkGetAutostart(virNetworkPtr network,
                                   int *autostart) {
3474 3475
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3476
    int ret = -1;
3477

3478
    testDriverLock(privconn);
3479 3480
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
3481
    testDriverUnlock(privconn);
3482 3483

    if (privnet == NULL) {
3484
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3485
        goto cleanup;
3486 3487
    }

3488
    *autostart = privnet->autostart;
3489 3490 3491
    ret = 0;

cleanup:
3492 3493
    if (privnet)
        virNetworkObjUnlock(privnet);
3494
    return ret;
3495 3496 3497 3498
}

static int testNetworkSetAutostart(virNetworkPtr network,
                                   int autostart) {
3499 3500
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3501
    int ret = -1;
3502

3503
    testDriverLock(privconn);
3504 3505
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
3506
    testDriverUnlock(privconn);
3507 3508

    if (privnet == NULL) {
3509
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3510
        goto cleanup;
3511 3512
    }

3513
    privnet->autostart = autostart ? 1 : 0;
3514 3515 3516
    ret = 0;

cleanup:
3517 3518
    if (privnet)
        virNetworkObjUnlock(privnet);
3519
    return ret;
3520
}
3521

C
Cole Robinson 已提交
3522

L
Laine Stump 已提交
3523 3524 3525 3526
/*
 * Physical host interface routines
 */

3527
static virDrvOpenStatus testInterfaceOpen(virConnectPtr conn,
L
Laine Stump 已提交
3528
                                          virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
3529
                                          unsigned int flags)
L
Laine Stump 已提交
3530
{
E
Eric Blake 已提交
3531 3532
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

L
Laine Stump 已提交
3533 3534 3535 3536 3537 3538 3539
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

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

3540
static int testInterfaceClose(virConnectPtr conn)
L
Laine Stump 已提交
3541 3542 3543 3544 3545 3546
{
    conn->interfacePrivateData = NULL;
    return 0;
}


3547
static int testConnectNumOfInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3548 3549
{
    testConnPtr privconn = conn->privateData;
3550 3551
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3552 3553

    testDriverLock(privconn);
3554
    for (i = 0; (i < privconn->ifaces.count); i++) {
L
Laine Stump 已提交
3555
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3556
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
L
Laine Stump 已提交
3557 3558 3559 3560 3561 3562 3563 3564
            count++;
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3565
static int testConnectListInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3566 3567
{
    testConnPtr privconn = conn->privateData;
3568 3569
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3570 3571 3572

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
3573
    for (i = 0; (i < privconn->ifaces.count) && (n < nnames); i++) {
L
Laine Stump 已提交
3574
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3575
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
3576
            if (VIR_STRDUP(names[n++], privconn->ifaces.objs[i]->def->name) < 0) {
L
Laine Stump 已提交
3577
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
3578
                goto error;
L
Laine Stump 已提交
3579 3580 3581 3582 3583 3584 3585 3586
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

3587
error:
3588
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3589 3590 3591 3592 3593
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

3594
static int testConnectNumOfDefinedInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3595 3596
{
    testConnPtr privconn = conn->privateData;
3597 3598
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3599 3600

    testDriverLock(privconn);
3601
    for (i = 0; i < privconn->ifaces.count; i++) {
L
Laine Stump 已提交
3602
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3603
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
L
Laine Stump 已提交
3604 3605 3606 3607 3608 3609 3610 3611
            count++;
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3612
static int testConnectListDefinedInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3613 3614
{
    testConnPtr privconn = conn->privateData;
3615 3616
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3617 3618 3619

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
3620
    for (i = 0; (i < privconn->ifaces.count) && (n < nnames); i++) {
L
Laine Stump 已提交
3621
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3622
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
3623
            if (VIR_STRDUP(names[n++], privconn->ifaces.objs[i]->def->name) < 0) {
L
Laine Stump 已提交
3624
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
3625
                goto error;
L
Laine Stump 已提交
3626 3627 3628 3629 3630 3631 3632 3633
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

3634
error:
3635
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3636 3637 3638 3639 3640
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

3641
static virInterfacePtr testInterfaceLookupByName(virConnectPtr conn,
L
Laine Stump 已提交
3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652
                                                 const char *name)
{
    testConnPtr privconn = conn->privateData;
    virInterfaceObjPtr iface;
    virInterfacePtr ret = NULL;

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

    if (iface == NULL) {
3653
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664
        goto cleanup;
    }

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

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

3665
static virInterfacePtr testInterfaceLookupByMACString(virConnectPtr conn,
L
Laine Stump 已提交
3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677
                                                      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) {
3678
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3679 3680 3681 3682
        goto cleanup;
    }

    if (ifacect > 1) {
3683
        virReportError(VIR_ERR_MULTIPLE_INTERFACES, NULL);
L
Laine Stump 已提交
3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694
        goto cleanup;
    }

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

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

3695 3696 3697 3698 3699 3700 3701 3702 3703 3704
static int testInterfaceIsActive(virInterfacePtr iface)
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virInterfaceFindByName(&privconn->ifaces, iface->name);
    testDriverUnlock(privconn);
    if (!obj) {
3705
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
3706 3707 3708 3709 3710 3711 3712 3713 3714 3715
        goto cleanup;
    }
    ret = virInterfaceObjIsActive(obj);

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

3716
static int testInterfaceChangeBegin(virConnectPtr conn,
E
Eric Blake 已提交
3717
                                    unsigned int flags)
3718 3719 3720 3721
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

E
Eric Blake 已提交
3722 3723
    virCheckFlags(0, -1);

3724 3725
    testDriverLock(privconn);
    if (privconn->transaction_running) {
3726
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3727
                       _("there is another transaction running."));
3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743
        goto cleanup;
    }

    privconn->transaction_running = true;

    if (virInterfaceObjListClone(&privconn->ifaces,
                                 &privconn->backupIfaces) < 0)
        goto cleanup;

    ret = 0;
cleanup:
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceChangeCommit(virConnectPtr conn,
E
Eric Blake 已提交
3744
                                     unsigned int flags)
3745 3746 3747 3748
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

E
Eric Blake 已提交
3749 3750
    virCheckFlags(0, -1);

3751 3752 3753
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3754
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3755 3756
                       _("no transaction running, "
                         "nothing to be committed."));
3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771
        goto cleanup;
    }

    virInterfaceObjListFree(&privconn->backupIfaces);
    privconn->transaction_running = false;

    ret = 0;

cleanup:
    testDriverUnlock(privconn);

    return ret;
}

static int testInterfaceChangeRollback(virConnectPtr conn,
E
Eric Blake 已提交
3772
                                       unsigned int flags)
3773 3774 3775 3776
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

E
Eric Blake 已提交
3777 3778
    virCheckFlags(0, -1);

3779 3780 3781
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3782
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3783 3784
                       _("no transaction running, "
                         "nothing to rollback."));
3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801
        goto cleanup;
    }

    virInterfaceObjListFree(&privconn->ifaces);
    privconn->ifaces.count = privconn->backupIfaces.count;
    privconn->ifaces.objs = privconn->backupIfaces.objs;
    privconn->backupIfaces.count = 0;
    privconn->backupIfaces.objs = NULL;

    privconn->transaction_running = false;

    ret = 0;

cleanup:
    testDriverUnlock(privconn);
    return ret;
}
3802

L
Laine Stump 已提交
3803
static char *testInterfaceGetXMLDesc(virInterfacePtr iface,
E
Eric Blake 已提交
3804
                                     unsigned int flags)
L
Laine Stump 已提交
3805 3806 3807 3808 3809
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr privinterface;
    char *ret = NULL;

E
Eric Blake 已提交
3810 3811
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
3812 3813 3814 3815 3816 3817
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);
    testDriverUnlock(privconn);

    if (privinterface == NULL) {
3818
        virReportError(VIR_ERR_NO_INTERFACE, __FUNCTION__);
L
Laine Stump 已提交
3819 3820 3821
        goto cleanup;
    }

3822
    ret = virInterfaceDefFormat(privinterface->def);
L
Laine Stump 已提交
3823 3824 3825 3826 3827 3828 3829 3830 3831

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


static virInterfacePtr testInterfaceDefineXML(virConnectPtr conn, const char *xmlStr,
E
Eric Blake 已提交
3832
                                              unsigned int flags)
L
Laine Stump 已提交
3833 3834 3835 3836 3837 3838
{
    testConnPtr privconn = conn->privateData;
    virInterfaceDefPtr def;
    virInterfaceObjPtr iface = NULL;
    virInterfacePtr ret = NULL;

E
Eric Blake 已提交
3839 3840
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
3841
    testDriverLock(privconn);
3842
    if ((def = virInterfaceDefParseString(xmlStr)) == NULL)
L
Laine Stump 已提交
3843 3844
        goto cleanup;

3845
    if ((iface = virInterfaceAssignDef(&privconn->ifaces, def)) == NULL)
L
Laine Stump 已提交
3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869
        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) {
3870
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883
        goto cleanup;
    }

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

cleanup:
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceCreate(virInterfacePtr iface,
E
Eric Blake 已提交
3884
                               unsigned int flags)
L
Laine Stump 已提交
3885 3886 3887 3888 3889
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr privinterface;
    int ret = -1;

E
Eric Blake 已提交
3890 3891
    virCheckFlags(0, -1);

L
Laine Stump 已提交
3892 3893 3894 3895 3896
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);

    if (privinterface == NULL) {
3897
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3898 3899 3900 3901
        goto cleanup;
    }

    if (privinterface->active != 0) {
3902
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916
        goto cleanup;
    }

    privinterface->active = 1;
    ret = 0;

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

static int testInterfaceDestroy(virInterfacePtr iface,
E
Eric Blake 已提交
3917
                                unsigned int flags)
L
Laine Stump 已提交
3918 3919 3920 3921 3922
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr privinterface;
    int ret = -1;

E
Eric Blake 已提交
3923 3924
    virCheckFlags(0, -1);

L
Laine Stump 已提交
3925 3926 3927 3928 3929
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);

    if (privinterface == NULL) {
3930
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3931 3932 3933 3934
        goto cleanup;
    }

    if (privinterface->active == 0) {
3935
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950
        goto cleanup;
    }

    privinterface->active = 0;
    ret = 0;

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



C
Cole Robinson 已提交
3951 3952 3953 3954
/*
 * Storage Driver routines
 */

3955

3956
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool) {
C
Cole Robinson 已提交
3957 3958 3959 3960 3961

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

3962
    return VIR_STRDUP(pool->configFile, "");
C
Cole Robinson 已提交
3963 3964
}

3965 3966
static virDrvOpenStatus testStorageOpen(virConnectPtr conn,
                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
3967 3968 3969 3970
                                        unsigned int flags)
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982
    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;
}

3983

C
Cole Robinson 已提交
3984 3985 3986
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
                            const unsigned char *uuid) {
3987
    testConnPtr privconn = conn->privateData;
3988 3989
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3990

3991
    testDriverLock(privconn);
3992
    pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid);
3993
    testDriverUnlock(privconn);
3994 3995

    if (pool == NULL) {
3996
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
3997
        goto cleanup;
C
Cole Robinson 已提交
3998 3999
    }

4000 4001
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4002 4003

cleanup:
4004 4005
    if (pool)
        virStoragePoolObjUnlock(pool);
4006
    return ret;
C
Cole Robinson 已提交
4007 4008 4009 4010 4011
}

static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
                            const char *name) {
4012
    testConnPtr privconn = conn->privateData;
4013 4014
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4015

4016
    testDriverLock(privconn);
4017
    pool = virStoragePoolObjFindByName(&privconn->pools, name);
4018
    testDriverUnlock(privconn);
4019 4020

    if (pool == NULL) {
4021
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4022
        goto cleanup;
C
Cole Robinson 已提交
4023 4024
    }

4025 4026
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4027 4028

cleanup:
4029 4030
    if (pool)
        virStoragePoolObjUnlock(pool);
4031
    return ret;
C
Cole Robinson 已提交
4032 4033 4034 4035 4036 4037 4038 4039
}

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

static int
4040
testConnectNumOfStoragePools(virConnectPtr conn) {
4041
    testConnPtr privconn = conn->privateData;
4042 4043
    int numActive = 0;
    size_t i;
C
Cole Robinson 已提交
4044

4045
    testDriverLock(privconn);
4046
    for (i = 0; i < privconn->pools.count; i++)
C
Cole Robinson 已提交
4047 4048
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numActive++;
4049
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4050 4051 4052 4053 4054

    return numActive;
}

static int
4055 4056 4057
testConnectListStoragePools(virConnectPtr conn,
                            char **const names,
                            int nnames) {
4058
    testConnPtr privconn = conn->privateData;
4059 4060
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
4061

4062
    testDriverLock(privconn);
C
Cole Robinson 已提交
4063
    memset(names, 0, sizeof(*names)*nnames);
4064
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
4065
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4066
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
4067
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
4068
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
4069
            goto error;
4070 4071 4072 4073
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4074 4075 4076

    return n;

4077
error:
4078
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
4079
        VIR_FREE(names[n]);
4080
    testDriverUnlock(privconn);
4081
    return -1;
C
Cole Robinson 已提交
4082 4083 4084
}

static int
4085
testConnectNumOfDefinedStoragePools(virConnectPtr conn) {
4086
    testConnPtr privconn = conn->privateData;
4087 4088
    int numInactive = 0;
    size_t i;
C
Cole Robinson 已提交
4089

4090
    testDriverLock(privconn);
4091
    for (i = 0; i < privconn->pools.count; i++) {
4092
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4093 4094
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numInactive++;
4095 4096 4097
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4098 4099 4100 4101 4102

    return numInactive;
}

static int
4103 4104 4105
testConnectListDefinedStoragePools(virConnectPtr conn,
                                   char **const names,
                                   int nnames) {
4106
    testConnPtr privconn = conn->privateData;
4107 4108
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
4109

4110
    testDriverLock(privconn);
C
Cole Robinson 已提交
4111
    memset(names, 0, sizeof(*names)*nnames);
4112
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
4113
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4114
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
4115
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
4116
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
4117
            goto error;
4118 4119 4120 4121
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4122 4123 4124

    return n;

4125
error:
4126
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
4127
        VIR_FREE(names[n]);
4128
    testDriverUnlock(privconn);
4129
    return -1;
C
Cole Robinson 已提交
4130 4131
}

4132
static int
4133 4134 4135
testConnectListAllStoragePools(virConnectPtr conn,
                               virStoragePoolPtr **pools,
                               unsigned int flags)
4136 4137 4138 4139 4140 4141 4142
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

    testDriverLock(privconn);
4143 4144
    ret = virStoragePoolObjListExport(conn, privconn->pools, pools,
                                      NULL, flags);
4145 4146 4147 4148
    testDriverUnlock(privconn);

    return ret;
}
C
Cole Robinson 已提交
4149

4150 4151 4152 4153 4154 4155 4156 4157 4158 4159
static int testStoragePoolIsActive(virStoragePoolPtr pool)
{
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virStoragePoolObjFindByUUID(&privconn->pools, pool->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
4160
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180
        goto cleanup;
    }
    ret = virStoragePoolObjIsActive(obj);

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

static int testStoragePoolIsPersistent(virStoragePoolPtr pool)
{
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virStoragePoolObjFindByUUID(&privconn->pools, pool->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
4181
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193
        goto cleanup;
    }
    ret = obj->configFile ? 1 : 0;

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



C
Cole Robinson 已提交
4194
static int
4195 4196
testStoragePoolCreate(virStoragePoolPtr pool,
                      unsigned int flags)
E
Eric Blake 已提交
4197
{
4198 4199
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4200
    int ret = -1;
4201

E
Eric Blake 已提交
4202 4203
    virCheckFlags(0, -1);

4204
    testDriverLock(privconn);
4205 4206
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4207
    testDriverUnlock(privconn);
4208 4209

    if (privpool == NULL) {
4210
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4211
        goto cleanup;
4212 4213
    }

4214
    if (virStoragePoolObjIsActive(privpool)) {
4215 4216
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4217 4218
        goto cleanup;
    }
C
Cole Robinson 已提交
4219 4220

    privpool->active = 1;
4221
    ret = 0;
C
Cole Robinson 已提交
4222

4223
cleanup:
4224 4225
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4226
    return ret;
C
Cole Robinson 已提交
4227 4228 4229
}

static char *
4230 4231 4232 4233
testConnectFindStoragePoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type,
                                  const char *srcSpec,
                                  unsigned int flags)
C
Cole Robinson 已提交
4234
{
4235 4236 4237 4238
    virStoragePoolSourcePtr source = NULL;
    int pool_type;
    char *ret = NULL;

E
Eric Blake 已提交
4239 4240
    virCheckFlags(0, NULL);

4241 4242
    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
4243 4244
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
4245 4246 4247 4248
        goto cleanup;
    }

    if (srcSpec) {
4249
        source = virStoragePoolDefParseSourceString(srcSpec, pool_type);
4250 4251 4252 4253 4254 4255 4256
        if (!source)
            goto cleanup;
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
4257
        ignore_value(VIR_STRDUP(ret, defaultPoolSourcesLogicalXML));
4258 4259 4260
        break;

    case VIR_STORAGE_POOL_NETFS:
4261
        if (!source || !source->hosts[0].name) {
4262 4263
            virReportError(VIR_ERR_INVALID_ARG,
                           "%s", _("hostname must be specified for netfs sources"));
4264 4265 4266
            goto cleanup;
        }

4267 4268
        ignore_value(virAsprintf(&ret, defaultPoolSourcesNetFSXML,
                                 source->hosts[0].name));
4269 4270 4271
        break;

    default:
4272 4273
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source discovery"), type);
4274 4275 4276 4277 4278
    }

cleanup:
    virStoragePoolSourceFree(source);
    return ret;
C
Cole Robinson 已提交
4279 4280 4281 4282
}


static virStoragePoolPtr
4283 4284 4285
testStoragePoolCreateXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4286
{
4287
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4288
    virStoragePoolDefPtr def;
4289
    virStoragePoolObjPtr pool = NULL;
4290
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4291

E
Eric Blake 已提交
4292 4293
    virCheckFlags(0, NULL);

4294
    testDriverLock(privconn);
4295
    if (!(def = virStoragePoolDefParseString(xml)))
4296
        goto cleanup;
C
Cole Robinson 已提交
4297

4298 4299 4300 4301
    pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid);
    if (!pool)
        pool = virStoragePoolObjFindByName(&privconn->pools, def->name);
    if (pool) {
4302 4303
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("storage pool already exists"));
4304
        goto cleanup;
C
Cole Robinson 已提交
4305 4306
    }

4307
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4308
        goto cleanup;
4309
    def = NULL;
C
Cole Robinson 已提交
4310

4311
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4312
        virStoragePoolObjRemove(&privconn->pools, pool);
4313 4314
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4315 4316 4317
    }
    pool->active = 1;

4318 4319
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4320 4321 4322

cleanup:
    virStoragePoolDefFree(def);
4323 4324 4325
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4326
    return ret;
C
Cole Robinson 已提交
4327 4328 4329
}

static virStoragePoolPtr
4330 4331 4332
testStoragePoolDefineXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4333
{
4334
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4335
    virStoragePoolDefPtr def;
4336
    virStoragePoolObjPtr pool = NULL;
4337
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4338

E
Eric Blake 已提交
4339 4340
    virCheckFlags(0, NULL);

4341
    testDriverLock(privconn);
4342
    if (!(def = virStoragePoolDefParseString(xml)))
4343
        goto cleanup;
C
Cole Robinson 已提交
4344 4345 4346 4347 4348

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

4349
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4350 4351
        goto cleanup;
    def = NULL;
C
Cole Robinson 已提交
4352

4353
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4354
        virStoragePoolObjRemove(&privconn->pools, pool);
4355 4356
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4357 4358
    }

4359 4360
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4361 4362 4363

cleanup:
    virStoragePoolDefFree(def);
4364 4365 4366
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4367
    return ret;
C
Cole Robinson 已提交
4368 4369 4370
}

static int
4371 4372 4373
testStoragePoolUndefine(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4374
    int ret = -1;
4375

4376
    testDriverLock(privconn);
4377 4378 4379 4380
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
4381
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4382
        goto cleanup;
4383 4384
    }

4385
    if (virStoragePoolObjIsActive(privpool)) {
4386 4387
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4388 4389
        goto cleanup;
    }
C
Cole Robinson 已提交
4390 4391

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

4394
cleanup:
4395 4396 4397
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
4398
    return ret;
C
Cole Robinson 已提交
4399 4400 4401
}

static int
4402
testStoragePoolBuild(virStoragePoolPtr pool,
E
Eric Blake 已提交
4403 4404
                     unsigned int flags)
{
4405 4406
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4407
    int ret = -1;
4408

E
Eric Blake 已提交
4409 4410
    virCheckFlags(0, -1);

4411
    testDriverLock(privconn);
4412 4413
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4414
    testDriverUnlock(privconn);
4415 4416

    if (privpool == NULL) {
4417
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4418
        goto cleanup;
4419 4420
    }

4421
    if (virStoragePoolObjIsActive(privpool)) {
4422 4423
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4424 4425
        goto cleanup;
    }
4426
    ret = 0;
C
Cole Robinson 已提交
4427

4428
cleanup:
4429 4430
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4431
    return ret;
C
Cole Robinson 已提交
4432 4433 4434 4435
}


static int
4436 4437 4438
testStoragePoolDestroy(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4439
    int ret = -1;
4440

4441
    testDriverLock(privconn);
4442 4443 4444 4445
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
4446
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4447
        goto cleanup;
4448 4449 4450
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4451 4452
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4453
        goto cleanup;
4454
    }
C
Cole Robinson 已提交
4455 4456 4457

    privpool->active = 0;

4458
    if (privpool->configFile == NULL) {
C
Cole Robinson 已提交
4459
        virStoragePoolObjRemove(&privconn->pools, privpool);
4460 4461
        privpool = NULL;
    }
4462
    ret = 0;
C
Cole Robinson 已提交
4463

4464
cleanup:
4465 4466 4467
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
4468
    return ret;
C
Cole Robinson 已提交
4469 4470 4471 4472
}


static int
4473
testStoragePoolDelete(virStoragePoolPtr pool,
E
Eric Blake 已提交
4474 4475
                      unsigned int flags)
{
4476 4477
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4478
    int ret = -1;
4479

E
Eric Blake 已提交
4480 4481
    virCheckFlags(0, -1);

4482
    testDriverLock(privconn);
4483 4484
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4485
    testDriverUnlock(privconn);
4486 4487

    if (privpool == NULL) {
4488
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4489 4490 4491 4492
        goto cleanup;
    }

    if (virStoragePoolObjIsActive(privpool)) {
4493 4494
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4495
        goto cleanup;
4496 4497
    }

4498
    ret = 0;
C
Cole Robinson 已提交
4499

4500
cleanup:
4501 4502
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4503
    return ret;
C
Cole Robinson 已提交
4504 4505 4506 4507
}


static int
4508
testStoragePoolRefresh(virStoragePoolPtr pool,
E
Eric Blake 已提交
4509 4510
                       unsigned int flags)
{
4511 4512
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4513
    int ret = -1;
4514

E
Eric Blake 已提交
4515 4516
    virCheckFlags(0, -1);

4517
    testDriverLock(privconn);
4518 4519
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4520
    testDriverUnlock(privconn);
4521 4522

    if (privpool == NULL) {
4523
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4524
        goto cleanup;
4525 4526 4527
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4528 4529
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4530
        goto cleanup;
4531
    }
4532
    ret = 0;
C
Cole Robinson 已提交
4533

4534
cleanup:
4535 4536
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4537
    return ret;
C
Cole Robinson 已提交
4538 4539 4540 4541
}


static int
4542
testStoragePoolGetInfo(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4543
                       virStoragePoolInfoPtr info) {
4544 4545
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4546
    int ret = -1;
4547

4548
    testDriverLock(privconn);
4549 4550
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4551
    testDriverUnlock(privconn);
4552 4553

    if (privpool == NULL) {
4554
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4555
        goto cleanup;
4556
    }
C
Cole Robinson 已提交
4557 4558 4559 4560 4561 4562 4563 4564 4565

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

4568
cleanup:
4569 4570
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4571
    return ret;
C
Cole Robinson 已提交
4572 4573 4574
}

static char *
4575
testStoragePoolGetXMLDesc(virStoragePoolPtr pool,
E
Eric Blake 已提交
4576 4577
                          unsigned int flags)
{
4578 4579
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4580
    char *ret = NULL;
4581

E
Eric Blake 已提交
4582 4583
    virCheckFlags(0, NULL);

4584
    testDriverLock(privconn);
4585 4586
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4587
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4588

4589
    if (privpool == NULL) {
4590
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4591
        goto cleanup;
4592 4593
    }

4594
    ret = virStoragePoolDefFormat(privpool->def);
4595 4596

cleanup:
4597 4598
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4599
    return ret;
C
Cole Robinson 已提交
4600 4601 4602
}

static int
4603
testStoragePoolGetAutostart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4604
                            int *autostart) {
4605 4606
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4607
    int ret = -1;
4608

4609
    testDriverLock(privconn);
4610 4611
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4612
    testDriverUnlock(privconn);
4613 4614

    if (privpool == NULL) {
4615
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4616
        goto cleanup;
4617
    }
C
Cole Robinson 已提交
4618 4619 4620 4621 4622 4623

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

4626
cleanup:
4627 4628
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4629
    return ret;
C
Cole Robinson 已提交
4630 4631 4632
}

static int
4633
testStoragePoolSetAutostart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4634
                            int autostart) {
4635 4636
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4637
    int ret = -1;
4638

4639
    testDriverLock(privconn);
4640 4641
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4642
    testDriverUnlock(privconn);
4643 4644

    if (privpool == NULL) {
4645
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4646
        goto cleanup;
4647
    }
C
Cole Robinson 已提交
4648 4649

    if (!privpool->configFile) {
4650 4651
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("pool has no config file"));
4652
        goto cleanup;
C
Cole Robinson 已提交
4653 4654 4655 4656
    }

    autostart = (autostart != 0);
    privpool->autostart = autostart;
4657 4658 4659
    ret = 0;

cleanup:
4660 4661
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4662
    return ret;
C
Cole Robinson 已提交
4663 4664 4665 4666
}


static int
4667
testStoragePoolNumOfVolumes(virStoragePoolPtr pool) {
4668 4669
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4670
    int ret = -1;
4671

4672
    testDriverLock(privconn);
4673 4674
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4675
    testDriverUnlock(privconn);
4676 4677

    if (privpool == NULL) {
4678
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4679
        goto cleanup;
4680 4681 4682
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4683 4684
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4685
        goto cleanup;
4686
    }
C
Cole Robinson 已提交
4687

4688 4689 4690
    ret = privpool->volumes.count;

cleanup:
4691 4692
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4693
    return ret;
C
Cole Robinson 已提交
4694 4695 4696
}

static int
4697
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4698 4699
                           char **const names,
                           int maxnames) {
4700 4701
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4702 4703
    size_t i = 0;
    int n = 0;
C
Cole Robinson 已提交
4704

4705
    memset(names, 0, maxnames * sizeof(*names));
4706 4707

    testDriverLock(privconn);
4708 4709
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4710
    testDriverUnlock(privconn);
4711 4712

    if (privpool == NULL) {
4713
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4714
        goto cleanup;
4715 4716 4717 4718
    }


    if (!virStoragePoolObjIsActive(privpool)) {
4719 4720
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4721
        goto cleanup;
4722 4723
    }

4724
    for (i = 0; i < privpool->volumes.count && n < maxnames; i++) {
4725
        if (VIR_STRDUP(names[n++], privpool->volumes.objs[i]->name) < 0)
C
Cole Robinson 已提交
4726 4727 4728
            goto cleanup;
    }

4729
    virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4730 4731 4732
    return n;

 cleanup:
4733
    for (n = 0; n < maxnames; n++)
C
Cole Robinson 已提交
4734 4735
        VIR_FREE(names[i]);

4736
    memset(names, 0, maxnames * sizeof(*names));
4737 4738
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4739 4740 4741
    return -1;
}

4742 4743 4744 4745 4746 4747
static int
testStoragePoolListAllVolumes(virStoragePoolPtr obj,
                              virStorageVolPtr **vols,
                              unsigned int flags) {
    testConnPtr privconn = obj->conn->privateData;
    virStoragePoolObjPtr pool;
4748
    size_t i;
4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777
    virStorageVolPtr *tmp_vols = NULL;
    virStorageVolPtr vol = NULL;
    int nvols = 0;
    int ret = -1;

    virCheckFlags(0, -1);

    testDriverLock(privconn);
    pool = virStoragePoolObjFindByUUID(&privconn->pools, obj->uuid);
    testDriverUnlock(privconn);

    if (!pool) {
        virReportError(VIR_ERR_NO_STORAGE_POOL, "%s",
                       _("no storage pool with matching uuid"));
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(pool)) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("storage pool is not active"));
        goto cleanup;
    }

     /* Just returns the volumes count */
    if (!vols) {
        ret = pool->volumes.count;
        goto cleanup;
    }

4778
    if (VIR_ALLOC_N(tmp_vols, pool->volumes.count + 1) < 0)
4779 4780
         goto cleanup;

4781
    for (i = 0; i < pool->volumes.count; i++) {
4782 4783
        if (!(vol = virGetStorageVol(obj->conn, pool->def->name,
                                     pool->volumes.objs[i]->name,
4784 4785
                                     pool->volumes.objs[i]->key,
                                     NULL, NULL)))
4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799
            goto cleanup;
        tmp_vols[nvols++] = vol;
    }

    *vols = tmp_vols;
    tmp_vols = NULL;
    ret = nvols;

 cleanup:
    if (tmp_vols) {
        for (i = 0; i < nvols; i++) {
            if (tmp_vols[i])
                virStorageVolFree(tmp_vols[i]);
        }
4800
        VIR_FREE(tmp_vols);
4801 4802 4803 4804 4805 4806 4807
    }

    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
C
Cole Robinson 已提交
4808 4809

static virStorageVolPtr
4810 4811
testStorageVolLookupByName(virStoragePoolPtr pool,
                           const char *name ATTRIBUTE_UNUSED) {
4812 4813 4814
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
4815
    virStorageVolPtr ret = NULL;
4816

4817
    testDriverLock(privconn);
4818 4819
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4820
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4821

4822
    if (privpool == NULL) {
4823
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4824
        goto cleanup;
4825 4826 4827 4828
    }


    if (!virStoragePoolObjIsActive(privpool)) {
4829 4830
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4831
        goto cleanup;
4832 4833 4834 4835 4836
    }

    privvol = virStorageVolDefFindByName(privpool, name);

    if (!privvol) {
4837 4838
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"), name);
4839
        goto cleanup;
C
Cole Robinson 已提交
4840 4841
    }

4842
    ret = virGetStorageVol(pool->conn, privpool->def->name,
4843 4844
                           privvol->name, privvol->key,
                           NULL, NULL);
4845 4846

cleanup:
4847 4848
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4849
    return ret;
C
Cole Robinson 已提交
4850 4851 4852 4853
}


static virStorageVolPtr
4854 4855
testStorageVolLookupByKey(virConnectPtr conn,
                          const char *key) {
4856
    testConnPtr privconn = conn->privateData;
4857
    size_t i;
4858
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4859

4860
    testDriverLock(privconn);
4861
    for (i = 0; i < privconn->pools.count; i++) {
4862
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4863
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4864
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4865 4866
                virStorageVolDefFindByKey(privconn->pools.objs[i], key);

4867 4868 4869 4870
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
4871 4872
                                       privvol->key,
                                       NULL, NULL);
4873
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
4874 4875
                break;
            }
C
Cole Robinson 已提交
4876
        }
4877
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4878
    }
4879
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4880

4881
    if (!ret)
4882 4883
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching key '%s'"), key);
4884 4885

    return ret;
C
Cole Robinson 已提交
4886 4887 4888
}

static virStorageVolPtr
4889 4890
testStorageVolLookupByPath(virConnectPtr conn,
                           const char *path) {
4891
    testConnPtr privconn = conn->privateData;
4892
    size_t i;
4893
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4894

4895
    testDriverLock(privconn);
4896
    for (i = 0; i < privconn->pools.count; i++) {
4897
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4898
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4899
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4900 4901
                virStorageVolDefFindByPath(privconn->pools.objs[i], path);

4902 4903 4904 4905
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
4906 4907
                                       privvol->key,
                                       NULL, NULL);
4908
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
4909 4910
                break;
            }
C
Cole Robinson 已提交
4911
        }
4912
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4913
    }
4914
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4915

4916
    if (!ret)
4917 4918
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching path '%s'"), path);
4919 4920

    return ret;
C
Cole Robinson 已提交
4921 4922 4923
}

static virStorageVolPtr
4924 4925 4926
testStorageVolCreateXML(virStoragePoolPtr pool,
                        const char *xmldesc,
                        unsigned int flags)
E
Eric Blake 已提交
4927
{
4928 4929
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4930 4931
    virStorageVolDefPtr privvol = NULL;
    virStorageVolPtr ret = NULL;
4932

E
Eric Blake 已提交
4933 4934
    virCheckFlags(0, NULL);

4935
    testDriverLock(privconn);
4936 4937
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4938
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4939

4940
    if (privpool == NULL) {
4941
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4942
        goto cleanup;
4943 4944 4945
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4946 4947
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4948
        goto cleanup;
4949
    }
C
Cole Robinson 已提交
4950

4951
    privvol = virStorageVolDefParseString(privpool->def, xmldesc);
4952
    if (privvol == NULL)
4953
        goto cleanup;
4954 4955

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
4956 4957
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
4958
        goto cleanup;
C
Cole Robinson 已提交
4959 4960 4961
    }

    /* Make sure enough space */
4962
    if ((privpool->def->allocation + privvol->allocation) >
C
Cole Robinson 已提交
4963
         privpool->def->capacity) {
4964 4965 4966
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
4967
        goto cleanup;
C
Cole Robinson 已提交
4968 4969 4970
    }

    if (VIR_REALLOC_N(privpool->volumes.objs,
4971
                      privpool->volumes.count+1) < 0)
4972
        goto cleanup;
C
Cole Robinson 已提交
4973

4974 4975
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
4976
                    privvol->name) == -1)
4977
        goto cleanup;
C
Cole Robinson 已提交
4978

4979
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0)
4980
        goto cleanup;
C
Cole Robinson 已提交
4981

4982
    privpool->def->allocation += privvol->allocation;
C
Cole Robinson 已提交
4983 4984 4985
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

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

4988
    ret = virGetStorageVol(pool->conn, privpool->def->name,
4989 4990
                           privvol->name, privvol->key,
                           NULL, NULL);
4991
    privvol = NULL;
4992 4993 4994

cleanup:
    virStorageVolDefFree(privvol);
4995 4996
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4997
    return ret;
C
Cole Robinson 已提交
4998 4999
}

5000
static virStorageVolPtr
5001 5002 5003 5004
testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
                            const char *xmldesc,
                            virStorageVolPtr clonevol,
                            unsigned int flags)
E
Eric Blake 已提交
5005
{
5006 5007 5008 5009 5010
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol = NULL, origvol = NULL;
    virStorageVolPtr ret = NULL;

E
Eric Blake 已提交
5011 5012
    virCheckFlags(0, NULL);

5013 5014 5015 5016 5017 5018
    testDriverLock(privconn);
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
    testDriverUnlock(privconn);

    if (privpool == NULL) {
5019
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5020 5021 5022 5023
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5024 5025
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
5026 5027 5028
        goto cleanup;
    }

5029
    privvol = virStorageVolDefParseString(privpool->def, xmldesc);
5030 5031 5032 5033
    if (privvol == NULL)
        goto cleanup;

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
5034 5035
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
5036 5037 5038 5039 5040
        goto cleanup;
    }

    origvol = virStorageVolDefFindByName(privpool, clonevol->name);
    if (!origvol) {
5041 5042 5043
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       clonevol->name);
5044 5045 5046 5047 5048 5049
        goto cleanup;
    }

    /* Make sure enough space */
    if ((privpool->def->allocation + privvol->allocation) >
         privpool->def->capacity) {
5050 5051 5052
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
5053 5054 5055 5056 5057 5058
        goto cleanup;
    }
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    if (VIR_REALLOC_N(privpool->volumes.objs,
5059
                      privpool->volumes.count+1) < 0)
5060 5061
        goto cleanup;

5062 5063
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
5064
                    privvol->name) == -1)
5065 5066
        goto cleanup;

5067
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0)
5068 5069 5070 5071 5072 5073 5074 5075 5076
        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,
5077 5078
                           privvol->name, privvol->key,
                           NULL, NULL);
5079 5080 5081 5082 5083 5084 5085 5086 5087
    privvol = NULL;

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

C
Cole Robinson 已提交
5088
static int
5089 5090
testStorageVolDelete(virStorageVolPtr vol,
                     unsigned int flags)
E
Eric Blake 已提交
5091
{
5092 5093 5094
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5095
    size_t i;
5096
    int ret = -1;
C
Cole Robinson 已提交
5097

E
Eric Blake 已提交
5098 5099
    virCheckFlags(0, -1);

5100
    testDriverLock(privconn);
5101 5102
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5103
    testDriverUnlock(privconn);
5104 5105

    if (privpool == NULL) {
5106
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5107
        goto cleanup;
5108 5109 5110 5111 5112 5113
    }


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

    if (privvol == NULL) {
5114 5115 5116
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5117
        goto cleanup;
5118 5119 5120
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5121 5122
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5123
        goto cleanup;
5124 5125 5126
    }


C
Cole Robinson 已提交
5127 5128 5129 5130
    privpool->def->allocation -= privvol->allocation;
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

5131
    for (i = 0; i < privpool->volumes.count; i++) {
C
Cole Robinson 已提交
5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149
        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;
        }
    }
5150
    ret = 0;
C
Cole Robinson 已提交
5151

5152
cleanup:
5153 5154
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5155
    return ret;
C
Cole Robinson 已提交
5156 5157 5158 5159 5160
}


static int testStorageVolumeTypeForPool(int pooltype) {

5161
    switch (pooltype) {
C
Cole Robinson 已提交
5162 5163 5164 5165 5166 5167 5168 5169 5170 5171
        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
5172 5173
testStorageVolGetInfo(virStorageVolPtr vol,
                      virStorageVolInfoPtr info) {
5174 5175 5176
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5177
    int ret = -1;
5178

5179
    testDriverLock(privconn);
5180 5181
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5182
    testDriverUnlock(privconn);
5183 5184

    if (privpool == NULL) {
5185
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5186
        goto cleanup;
5187 5188 5189 5190 5191
    }

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

    if (privvol == NULL) {
5192 5193 5194
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5195
        goto cleanup;
5196 5197 5198
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5199 5200
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5201
        goto cleanup;
5202
    }
C
Cole Robinson 已提交
5203 5204 5205 5206 5207

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

5210
cleanup:
5211 5212
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5213
    return ret;
C
Cole Robinson 已提交
5214 5215 5216
}

static char *
5217 5218
testStorageVolGetXMLDesc(virStorageVolPtr vol,
                         unsigned int flags)
E
Eric Blake 已提交
5219
{
5220 5221 5222
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5223
    char *ret = NULL;
5224

E
Eric Blake 已提交
5225 5226
    virCheckFlags(0, NULL);

5227
    testDriverLock(privconn);
5228 5229
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5230
    testDriverUnlock(privconn);
5231 5232

    if (privpool == NULL) {
5233
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5234
        goto cleanup;
5235 5236 5237 5238 5239
    }

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

    if (privvol == NULL) {
5240 5241 5242
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5243
        goto cleanup;
5244
    }
C
Cole Robinson 已提交
5245

5246
    if (!virStoragePoolObjIsActive(privpool)) {
5247 5248
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5249
        goto cleanup;
5250 5251
    }

5252
    ret = virStorageVolDefFormat(privpool->def, privvol);
5253 5254

cleanup:
5255 5256
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5257
    return ret;
C
Cole Robinson 已提交
5258 5259 5260
}

static char *
5261
testStorageVolGetPath(virStorageVolPtr vol) {
5262 5263 5264
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5265
    char *ret = NULL;
5266

5267
    testDriverLock(privconn);
5268 5269
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5270
    testDriverUnlock(privconn);
5271 5272

    if (privpool == NULL) {
5273
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5274
        goto cleanup;
5275 5276 5277 5278 5279
    }

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

    if (privvol == NULL) {
5280 5281 5282
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5283
        goto cleanup;
5284 5285 5286
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5287 5288
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5289
        goto cleanup;
5290 5291
    }

5292
    ignore_value(VIR_STRDUP(ret, privvol->target.path));
5293 5294

cleanup:
5295 5296
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
5297 5298 5299
    return ret;
}

5300

5301
/* Node device implementations */
5302 5303 5304
static virDrvOpenStatus testNodeDeviceOpen(virConnectPtr conn,
                                           virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                           unsigned int flags)
E
Eric Blake 已提交
5305 5306 5307
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

5308 5309 5310
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

5311
    conn->nodeDevicePrivateData = conn->privateData;
5312 5313 5314
    return VIR_DRV_OPEN_SUCCESS;
}

5315 5316
static int testNodeDeviceClose(virConnectPtr conn) {
    conn->nodeDevicePrivateData = NULL;
5317 5318 5319
    return 0;
}

5320 5321 5322
static int
testNodeNumOfDevices(virConnectPtr conn,
                     const char *cap,
E
Eric Blake 已提交
5323
                     unsigned int flags)
5324 5325 5326
{
    testConnPtr driver = conn->privateData;
    int ndevs = 0;
5327
    size_t i;
5328

E
Eric Blake 已提交
5329 5330
    virCheckFlags(0, -1);

5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345
    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,
E
Eric Blake 已提交
5346
                    unsigned int flags)
5347 5348 5349
{
    testConnPtr driver = conn->privateData;
    int ndevs = 0;
5350
    size_t i;
5351

E
Eric Blake 已提交
5352 5353
    virCheckFlags(0, -1);

5354 5355 5356 5357 5358
    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)) {
5359
            if (VIR_STRDUP(names[ndevs++], driver->devs.objs[i]->def->name) < 0) {
5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389
                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) {
5390
        virReportError(VIR_ERR_NO_NODE_DEVICE, NULL);
5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402
        goto cleanup;
    }

    ret = virGetNodeDevice(conn, name);

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

static char *
5403
testNodeDeviceGetXMLDesc(virNodeDevicePtr dev,
E
Eric Blake 已提交
5404
                         unsigned int flags)
5405 5406 5407 5408 5409
{
    testConnPtr driver = dev->conn->privateData;
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

E
Eric Blake 已提交
5410 5411
    virCheckFlags(0, NULL);

5412 5413 5414 5415 5416
    testDriverLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
    testDriverUnlock(driver);

    if (!obj) {
5417 5418 5419
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5420 5421 5422
        goto cleanup;
    }

5423
    ret = virNodeDeviceDefFormat(obj->def);
5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442

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) {
5443 5444 5445
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5446 5447 5448 5449
        goto cleanup;
    }

    if (obj->def->parent) {
5450
        ignore_value(VIR_STRDUP(ret, obj->def->parent));
5451
    } else {
5452 5453
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no parent for this device"));
5454 5455 5456 5457 5458 5459 5460 5461
    }

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

5462

5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476
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) {
5477 5478 5479
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507
        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) {
5508 5509 5510
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5511 5512 5513 5514
        goto cleanup;
    }

    for (caps = obj->def->caps; caps && ncaps < maxnames; caps = caps->next) {
5515
        if (VIR_STRDUP(names[ncaps++], virNodeDevCapTypeToString(caps->type)) < 0)
5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530
            goto cleanup;
    }
    ret = ncaps;

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

5531 5532 5533
static virNodeDevicePtr
testNodeDeviceCreateXML(virConnectPtr conn,
                        const char *xmlDesc,
E
Eric Blake 已提交
5534
                        unsigned int flags)
5535 5536 5537 5538 5539 5540 5541 5542 5543
{
    testConnPtr driver = conn->privateData;
    virNodeDeviceDefPtr def = NULL;
    virNodeDeviceObjPtr obj = NULL;
    char *wwnn = NULL, *wwpn = NULL;
    int parent_host = -1;
    virNodeDevicePtr dev = NULL;
    virNodeDevCapsDefPtr caps;

E
Eric Blake 已提交
5544 5545
    virCheckFlags(0, NULL);

5546 5547
    testDriverLock(driver);

5548
    def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, NULL);
5549 5550 5551 5552 5553
    if (def == NULL) {
        goto cleanup;
    }

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

5558
    if (virNodeDeviceGetParentHost(&driver->devs,
5559 5560 5561 5562 5563 5564 5565 5566 5567
                                   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);
5568
    if (VIR_STRDUP(def->name, wwpn) < 0)
5569 5570 5571 5572 5573 5574 5575 5576 5577
        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;

5578
        caps->data.scsi_host.host = virRandomBits(10);
5579 5580 5581 5582
        caps = caps->next;
    }


5583
    if (!(obj = virNodeDeviceAssignDef(&driver->devs, def))) {
5584 5585 5586 5587 5588 5589 5590 5591
        goto cleanup;
    }
    virNodeDeviceObjUnlock(obj);

    dev = virGetNodeDevice(conn, def->name);
    def = NULL;
cleanup:
    testDriverUnlock(driver);
5592
    virNodeDeviceDefFree(def);
5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611
    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) {
5612
        virReportError(VIR_ERR_NO_NODE_DEVICE, NULL);
5613 5614 5615
        goto out;
    }

5616
    if (virNodeDeviceGetWWNs(obj->def, &wwnn, &wwpn) == -1) {
5617 5618 5619
        goto out;
    }

5620
    if (VIR_STRDUP(parent_name, obj->def->parent) < 0)
5621 5622 5623 5624 5625 5626 5627 5628 5629
        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 */
5630
    if (virNodeDeviceGetParentHost(&driver->devs,
5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649
                                   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;
}

5650 5651

/* Domain event implementations */
5652
static int
5653 5654 5655 5656
testConnectDomainEventRegister(virConnectPtr conn,
                               virConnectDomainEventCallback callback,
                               void *opaque,
                               virFreeCallback freecb)
5657 5658 5659 5660 5661
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
5662 5663 5664
    ret = virDomainEventStateRegister(conn,
                                      driver->domainEventState,
                                      callback, opaque, freecb);
5665 5666 5667 5668 5669
    testDriverUnlock(driver);

    return ret;
}

5670

5671
static int
5672 5673
testConnectDomainEventDeregister(virConnectPtr conn,
                                 virConnectDomainEventCallback callback)
5674 5675 5676 5677 5678
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
5679 5680 5681
    ret = virDomainEventStateDeregister(conn,
                                        driver->domainEventState,
                                        callback);
5682 5683 5684 5685 5686
    testDriverUnlock(driver);

    return ret;
}

5687 5688

static int
5689 5690 5691 5692 5693 5694
testConnectDomainEventRegisterAny(virConnectPtr conn,
                                  virDomainPtr dom,
                                  int eventID,
                                  virConnectDomainEventGenericCallback callback,
                                  void *opaque,
                                  virFreeCallback freecb)
5695 5696 5697 5698 5699
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
5700 5701 5702 5703
    if (virDomainEventStateRegisterID(conn,
                                      driver->domainEventState,
                                      dom, eventID,
                                      callback, opaque, freecb, &ret) < 0)
5704
        ret = -1;
5705 5706 5707 5708 5709 5710
    testDriverUnlock(driver);

    return ret;
}

static int
5711 5712
testConnectDomainEventDeregisterAny(virConnectPtr conn,
                                    int callbackID)
5713 5714 5715 5716 5717
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
5718 5719 5720
    ret = virDomainEventStateDeregisterID(conn,
                                          driver->domainEventState,
                                          callbackID);
5721 5722 5723 5724 5725 5726
    testDriverUnlock(driver);

    return ret;
}


5727 5728 5729 5730
/* driver must be locked before calling */
static void testDomainEventQueue(testConnPtr driver,
                                 virDomainEventPtr event)
{
5731
    virDomainEventStateQueue(driver->domainEventState, event);
5732 5733
}

5734 5735
static virDrvOpenStatus testSecretOpen(virConnectPtr conn,
                                       virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
5736 5737 5738 5739
                                       unsigned int flags)
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

5740 5741 5742
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

5743
    conn->secretPrivateData = conn->privateData;
5744 5745 5746 5747 5748 5749 5750
    return VIR_DRV_OPEN_SUCCESS;
}

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

5752 5753 5754

static virDrvOpenStatus testNWFilterOpen(virConnectPtr conn,
                                         virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
5755 5756 5757 5758
                                         unsigned int flags)
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

5759 5760 5761
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

5762
    conn->nwfilterPrivateData = conn->privateData;
5763 5764 5765 5766 5767 5768 5769 5770
    return VIR_DRV_OPEN_SUCCESS;
}

static int testNWFilterClose(virConnectPtr conn) {
    conn->nwfilterPrivateData = NULL;
    return 0;
}

5771

5772 5773 5774
static int testConnectListAllDomains(virConnectPtr conn,
                                     virDomainPtr **domains,
                                     unsigned int flags)
5775 5776 5777 5778
{
    testConnPtr privconn = conn->privateData;
    int ret;

O
Osier Yang 已提交
5779
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
5780 5781

    testDriverLock(privconn);
5782 5783
    ret = virDomainObjListExport(privconn->domains, conn, domains,
                                 NULL, flags);
5784 5785 5786 5787 5788
    testDriverUnlock(privconn);

    return ret;
}

5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801
static int
testNodeGetCPUMap(virConnectPtr conn,
                  unsigned char **cpumap,
                  unsigned int *online,
                  unsigned int flags)
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

    virCheckFlags(0, -1);

    testDriverLock(privconn);
    if (cpumap) {
5802
        if (VIR_ALLOC_N(*cpumap, 1) < 0)
5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816
            goto cleanup;
        *cpumap[0] = 0x15;
    }

    if (online)
        *online = 3;

    ret = 8;

cleanup:
    testDriverUnlock(privconn);
    return ret;
}

5817 5818 5819 5820 5821 5822 5823 5824 5825 5826
static char *
testDomainScreenshot(virDomainPtr dom ATTRIBUTE_UNUSED,
                     virStreamPtr st,
                     unsigned int screen ATTRIBUTE_UNUSED,
                     unsigned int flags)
{
    char *ret = NULL;

    virCheckFlags(0, NULL);

5827
    if (VIR_STRDUP(ret, "image/png") < 0)
5828 5829 5830 5831 5832 5833 5834 5835
        return NULL;

    if (virFDStreamOpenFile(st, PKGDATADIR "/libvirtLogo.png", 0, 0, O_RDONLY < 0))
        VIR_FREE(ret);

    return ret;
}

5836

5837
static virDriver testDriver = {
5838 5839
    .no = VIR_DRV_TEST,
    .name = "Test",
5840 5841 5842
    .connectOpen = testConnectOpen, /* 0.1.1 */
    .connectClose = testConnectClose, /* 0.1.1 */
    .connectGetVersion = testConnectGetVersion, /* 0.1.1 */
5843
    .connectGetHostname = testConnectGetHostname, /* 0.6.3 */
5844
    .connectGetMaxVcpus = testConnectGetMaxVcpus, /* 0.3.2 */
5845
    .nodeGetInfo = testNodeGetInfo, /* 0.1.1 */
5846 5847 5848 5849
    .connectGetCapabilities = testConnectGetCapabilities, /* 0.2.1 */
    .connectListDomains = testConnectListDomains, /* 0.1.1 */
    .connectNumOfDomains = testConnectNumOfDomains, /* 0.1.1 */
    .connectListAllDomains = testConnectListAllDomains, /* 0.9.13 */
5850
    .domainCreateXML = testDomainCreateXML, /* 0.1.4 */
5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864
    .domainLookupByID = testDomainLookupByID, /* 0.1.1 */
    .domainLookupByUUID = testDomainLookupByUUID, /* 0.1.1 */
    .domainLookupByName = testDomainLookupByName, /* 0.1.1 */
    .domainSuspend = testDomainSuspend, /* 0.1.1 */
    .domainResume = testDomainResume, /* 0.1.1 */
    .domainShutdown = testDomainShutdown, /* 0.1.1 */
    .domainShutdownFlags = testDomainShutdownFlags, /* 0.9.10 */
    .domainReboot = testDomainReboot, /* 0.1.1 */
    .domainDestroy = testDomainDestroy, /* 0.1.1 */
    .domainGetOSType = testDomainGetOSType, /* 0.1.9 */
    .domainGetMaxMemory = testDomainGetMaxMemory, /* 0.1.4 */
    .domainSetMaxMemory = testDomainSetMaxMemory, /* 0.1.1 */
    .domainSetMemory = testDomainSetMemory, /* 0.1.4 */
    .domainGetInfo = testDomainGetInfo, /* 0.1.1 */
5865 5866
    .domainGetState = testDomainGetState, /* 0.9.2 */
    .domainSave = testDomainSave, /* 0.3.2 */
5867
    .domainSaveFlags = testDomainSaveFlags, /* 0.9.4 */
5868
    .domainRestore = testDomainRestore, /* 0.3.2 */
5869
    .domainRestoreFlags = testDomainRestoreFlags, /* 0.9.4 */
5870
    .domainCoreDump = testDomainCoreDump, /* 0.3.2 */
5871
    .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */
5872 5873 5874 5875 5876 5877
    .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */
    .domainGetVcpusFlags = testDomainGetVcpusFlags, /* 0.8.5 */
    .domainPinVcpu = testDomainPinVcpu, /* 0.7.3 */
    .domainGetVcpus = testDomainGetVcpus, /* 0.7.3 */
    .domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
    .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
5878 5879
    .connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
    .connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
5880 5881 5882 5883
    .domainCreate = testDomainCreate, /* 0.1.11 */
    .domainCreateWithFlags = testDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = testDomainDefineXML, /* 0.1.11 */
    .domainUndefine = testDomainUndefine, /* 0.1.11 */
5884
    .domainUndefineFlags = testDomainUndefineFlags, /* 0.9.4 */
5885 5886 5887
    .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
    .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
    .domainGetSchedulerType = testDomainGetSchedulerType, /* 0.3.2 */
5888 5889 5890 5891
    .domainGetSchedulerParameters = testDomainGetSchedulerParameters, /* 0.3.2 */
    .domainGetSchedulerParametersFlags = testDomainGetSchedulerParametersFlags, /* 0.9.2 */
    .domainSetSchedulerParameters = testDomainSetSchedulerParameters, /* 0.3.2 */
    .domainSetSchedulerParametersFlags = testDomainSetSchedulerParametersFlags, /* 0.9.2 */
5892 5893 5894
    .domainBlockStats = testDomainBlockStats, /* 0.7.0 */
    .domainInterfaceStats = testDomainInterfaceStats, /* 0.7.0 */
    .nodeGetCellsFreeMemory = testNodeGetCellsFreeMemory, /* 0.4.2 */
5895 5896 5897 5898
    .connectDomainEventRegister = testConnectDomainEventRegister, /* 0.6.0 */
    .connectDomainEventDeregister = testConnectDomainEventDeregister, /* 0.6.0 */
    .connectIsEncrypted = testConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = testConnectIsSecure, /* 0.7.3 */
5899 5900 5901
    .domainIsActive = testDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = testDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = testDomainIsUpdated, /* 0.8.6 */
5902 5903 5904
    .connectDomainEventRegisterAny = testConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = testConnectDomainEventDeregisterAny, /* 0.8.0 */
    .connectIsAlive = testConnectIsAlive, /* 0.9.8 */
5905
    .nodeGetCPUMap = testNodeGetCPUMap, /* 1.0.0 */
5906
    .domainScreenshot = testDomainScreenshot, /* 1.0.5 */
5907 5908 5909 5910
};

static virNetworkDriver testNetworkDriver = {
    "Test",
5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921
    .networkOpen = testNetworkOpen, /* 0.3.2 */
    .networkClose = testNetworkClose, /* 0.3.2 */
    .connectNumOfNetworks = testConnectNumOfNetworks, /* 0.3.2 */
    .connectListNetworks = testConnectListNetworks, /* 0.3.2 */
    .connectNumOfDefinedNetworks = testConnectNumOfDefinedNetworks, /* 0.3.2 */
    .connectListDefinedNetworks = testConnectListDefinedNetworks, /* 0.3.2 */
    .connectListAllNetworks = testConnectListAllNetworks, /* 0.10.2 */
    .networkLookupByUUID = testNetworkLookupByUUID, /* 0.3.2 */
    .networkLookupByName = testNetworkLookupByName, /* 0.3.2 */
    .networkCreateXML = testNetworkCreateXML, /* 0.3.2 */
    .networkDefineXML = testNetworkDefineXML, /* 0.3.2 */
5922
    .networkUndefine = testNetworkUndefine, /* 0.3.2 */
5923
    .networkUpdate = testNetworkUpdate, /* 0.10.2 */
5924
    .networkCreate = testNetworkCreate, /* 0.3.2 */
5925 5926 5927 5928 5929 5930 5931
    .networkDestroy = testNetworkDestroy, /* 0.3.2 */
    .networkGetXMLDesc = testNetworkGetXMLDesc, /* 0.3.2 */
    .networkGetBridgeName = testNetworkGetBridgeName, /* 0.3.2 */
    .networkGetAutostart = testNetworkGetAutostart, /* 0.3.2 */
    .networkSetAutostart = testNetworkSetAutostart, /* 0.3.2 */
    .networkIsActive = testNetworkIsActive, /* 0.7.3 */
    .networkIsPersistent = testNetworkIsPersistent, /* 0.7.3 */
5932 5933
};

L
Laine Stump 已提交
5934 5935
static virInterfaceDriver testInterfaceDriver = {
    "Test",                     /* name */
5936 5937 5938 5939 5940 5941 5942 5943
    .interfaceOpen = testInterfaceOpen, /* 0.7.0 */
    .interfaceClose = testInterfaceClose, /* 0.7.0 */
    .connectNumOfInterfaces = testConnectNumOfInterfaces, /* 0.7.0 */
    .connectListInterfaces = testConnectListInterfaces, /* 0.7.0 */
    .connectNumOfDefinedInterfaces = testConnectNumOfDefinedInterfaces, /* 0.7.0 */
    .connectListDefinedInterfaces = testConnectListDefinedInterfaces, /* 0.7.0 */
    .interfaceLookupByName = testInterfaceLookupByName, /* 0.7.0 */
    .interfaceLookupByMACString = testInterfaceLookupByMACString, /* 0.7.0 */
5944 5945 5946 5947 5948 5949
    .interfaceGetXMLDesc = testInterfaceGetXMLDesc, /* 0.7.0 */
    .interfaceDefineXML = testInterfaceDefineXML, /* 0.7.0 */
    .interfaceUndefine = testInterfaceUndefine, /* 0.7.0 */
    .interfaceCreate = testInterfaceCreate, /* 0.7.0 */
    .interfaceDestroy = testInterfaceDestroy, /* 0.7.0 */
    .interfaceIsActive = testInterfaceIsActive, /* 0.7.3 */
5950 5951 5952
    .interfaceChangeBegin = testInterfaceChangeBegin,   /* 0.9.2 */
    .interfaceChangeCommit = testInterfaceChangeCommit,  /* 0.9.2 */
    .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */
L
Laine Stump 已提交
5953 5954 5955
};


5956 5957
static virStorageDriver testStorageDriver = {
    .name = "Test",
5958 5959
    .storageOpen = testStorageOpen, /* 0.4.1 */
    .storageClose = testStorageClose, /* 0.4.1 */
5960

5961 5962 5963 5964 5965 5966
    .connectNumOfStoragePools = testConnectNumOfStoragePools, /* 0.5.0 */
    .connectListStoragePools = testConnectListStoragePools, /* 0.5.0 */
    .connectNumOfDefinedStoragePools = testConnectNumOfDefinedStoragePools, /* 0.5.0 */
    .connectListDefinedStoragePools = testConnectListDefinedStoragePools, /* 0.5.0 */
    .connectListAllStoragePools = testConnectListAllStoragePools, /* 0.10.2 */
    .connectFindStoragePoolSources = testConnectFindStoragePoolSources, /* 0.5.0 */
5967 5968 5969
    .storagePoolLookupByName = testStoragePoolLookupByName, /* 0.5.0 */
    .storagePoolLookupByUUID = testStoragePoolLookupByUUID, /* 0.5.0 */
    .storagePoolLookupByVolume = testStoragePoolLookupByVolume, /* 0.5.0 */
5970 5971
    .storagePoolCreateXML = testStoragePoolCreateXML, /* 0.5.0 */
    .storagePoolDefineXML = testStoragePoolDefineXML, /* 0.5.0 */
5972 5973
    .storagePoolBuild = testStoragePoolBuild, /* 0.5.0 */
    .storagePoolUndefine = testStoragePoolUndefine, /* 0.5.0 */
5974
    .storagePoolCreate = testStoragePoolCreate, /* 0.5.0 */
5975 5976 5977 5978 5979 5980 5981
    .storagePoolDestroy = testStoragePoolDestroy, /* 0.5.0 */
    .storagePoolDelete = testStoragePoolDelete, /* 0.5.0 */
    .storagePoolRefresh = testStoragePoolRefresh, /* 0.5.0 */
    .storagePoolGetInfo = testStoragePoolGetInfo, /* 0.5.0 */
    .storagePoolGetXMLDesc = testStoragePoolGetXMLDesc, /* 0.5.0 */
    .storagePoolGetAutostart = testStoragePoolGetAutostart, /* 0.5.0 */
    .storagePoolSetAutostart = testStoragePoolSetAutostart, /* 0.5.0 */
5982
    .storagePoolNumOfVolumes = testStoragePoolNumOfVolumes, /* 0.5.0 */
5983 5984 5985
    .storagePoolListVolumes = testStoragePoolListVolumes, /* 0.5.0 */
    .storagePoolListAllVolumes = testStoragePoolListAllVolumes, /* 0.10.2 */

5986 5987 5988 5989 5990 5991 5992 5993 5994
    .storageVolLookupByName = testStorageVolLookupByName, /* 0.5.0 */
    .storageVolLookupByKey = testStorageVolLookupByKey, /* 0.5.0 */
    .storageVolLookupByPath = testStorageVolLookupByPath, /* 0.5.0 */
    .storageVolCreateXML = testStorageVolCreateXML, /* 0.5.0 */
    .storageVolCreateXMLFrom = testStorageVolCreateXMLFrom, /* 0.6.4 */
    .storageVolDelete = testStorageVolDelete, /* 0.5.0 */
    .storageVolGetInfo = testStorageVolGetInfo, /* 0.5.0 */
    .storageVolGetXMLDesc = testStorageVolGetXMLDesc, /* 0.5.0 */
    .storageVolGetPath = testStorageVolGetPath, /* 0.5.0 */
5995 5996
    .storagePoolIsActive = testStoragePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = testStoragePoolIsPersistent, /* 0.7.3 */
5997 5998
};

5999
static virNodeDeviceDriver testNodeDeviceDriver = {
6000
    .name = "Test",
6001 6002
    .nodeDeviceOpen = testNodeDeviceOpen, /* 0.6.0 */
    .nodeDeviceClose = testNodeDeviceClose, /* 0.6.0 */
6003 6004 6005 6006 6007 6008 6009 6010 6011 6012

    .nodeNumOfDevices = testNodeNumOfDevices, /* 0.7.2 */
    .nodeListDevices = testNodeListDevices, /* 0.7.2 */
    .nodeDeviceLookupByName = testNodeDeviceLookupByName, /* 0.7.2 */
    .nodeDeviceGetXMLDesc = testNodeDeviceGetXMLDesc, /* 0.7.2 */
    .nodeDeviceGetParent = testNodeDeviceGetParent, /* 0.7.2 */
    .nodeDeviceNumOfCaps = testNodeDeviceNumOfCaps, /* 0.7.2 */
    .nodeDeviceListCaps = testNodeDeviceListCaps, /* 0.7.2 */
    .nodeDeviceCreateXML = testNodeDeviceCreateXML, /* 0.7.3 */
    .nodeDeviceDestroy = testNodeDeviceDestroy, /* 0.7.3 */
6013 6014
};

6015 6016
static virSecretDriver testSecretDriver = {
    .name = "Test",
6017 6018
    .secretOpen = testSecretOpen, /* 0.7.1 */
    .secretClose = testSecretClose, /* 0.7.1 */
6019
};
6020 6021


6022 6023
static virNWFilterDriver testNWFilterDriver = {
    .name = "Test",
6024 6025
    .nwfilterOpen = testNWFilterOpen, /* 0.8.0 */
    .nwfilterClose = testNWFilterClose, /* 0.8.0 */
6026 6027
};

6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
    if (virRegisterDriver(&testDriver) < 0)
        return -1;
    if (virRegisterNetworkDriver(&testNetworkDriver) < 0)
        return -1;
L
Laine Stump 已提交
6040 6041
    if (virRegisterInterfaceDriver(&testInterfaceDriver) < 0)
        return -1;
6042 6043
    if (virRegisterStorageDriver(&testStorageDriver) < 0)
        return -1;
6044
    if (virRegisterNodeDeviceDriver(&testNodeDeviceDriver) < 0)
6045
        return -1;
6046 6047
    if (virRegisterSecretDriver(&testSecretDriver) < 0)
        return -1;
6048 6049
    if (virRegisterNWFilterDriver(&testNWFilterDriver) < 0)
        return -1;
6050

6051 6052
    return 0;
}