test_driver.c 165.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
"  <bridge name='virbr0'/>"
254 255 256
"  <forward/>"
"  <ip address='192.168.122.1' netmask='255.255.255.0'>"
"    <dhcp>"
257
"      <range start='192.168.122.2' end='192.168.122.254'/>"
258 259 260
"    </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
/* Helper to update info for a single VCPU */
static int
382
testDomainUpdateVCPU(virDomainObjPtr dom,
383 384 385 386 387 388 389
                     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);
390
    size_t j;
H
Hu Tao 已提交
391
    bool cpu;
392 393 394 395 396 397 398 399 400 401 402

    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 已提交
403 404 405
            if (virBitmapGetBit(dom->def->cpumask, j, &cpu) < 0)
                return -1;
            if (cpu) {
406 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
                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
432
testDomainUpdateVCPUs(testConnPtr privconn,
433 434 435 436 437
                      virDomainObjPtr dom,
                      int nvcpus,
                      unsigned int clear_all)
{
    testDomainObjPrivatePtr privdata = dom->privateData;
438 439
    size_t i;
    int ret = -1;
440 441 442 443 444
    int cpumaplen, maxcpu;

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

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

448
    if (VIR_REALLOC_N(privdata->cpumaps, nvcpus * cpumaplen) < 0)
449 450 451 452 453
        goto cleanup;

    /* Set running VCPU and cpumap state */
    if (clear_all) {
        for (i = 0; i < nvcpus; ++i)
454
            if (testDomainUpdateVCPU(dom, i, cpumaplen, maxcpu) < 0)
455 456 457 458 459
                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)
460
            if (testDomainUpdateVCPU(dom, i, cpumaplen, maxcpu) < 0)
461 462 463
                goto cleanup;
    }

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

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

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

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

495
    if (testDomainUpdateVCPUs(privconn, dom, dom->def->vcpus, 1) < 0)
496 497
        goto cleanup;

J
Jiri Denemark 已提交
498
    virDomainObjSetState(dom, VIR_DOMAIN_RUNNING, reason);
499 500
    dom->def->id = privconn->nextDomID++;

501
    if (virDomainObjSetDefTransient(privconn->caps,
502
                                    privconn->xmlopt,
503
                                    dom, false) < 0) {
504 505 506
        goto cleanup;
    }

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

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

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

537
    testDriverLock(privconn);
538
    conn->privateData = privconn;
539

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

543
    memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));
544

545
    /* Numa setup */
546 547 548 549 550
    privconn->numCells = 2;
    for (u = 0; u < 2; ++u) {
        privconn->cells[u].numCpus = 8;
        privconn->cells[u].mem = (u + 1) * 2048 * 1024;
    }
551
    for (u = 0; u < 16; u++) {
552
        virBitmapPtr siblings = virBitmapNew(16);
553
        if (!siblings)
554 555 556 557 558 559
            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;
560 561
    }

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

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

568 569
    privconn->nextDomID = 1;

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

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

586
    domobj->persistent = 1;
587 588
    if (testDomainStartState(privconn, domobj,
                             VIR_DOMAIN_RUNNING_BOOTED) < 0) {
589
        virObjectUnlock(domobj);
590 591 592
        goto error;
    }

593
    virObjectUnlock(domobj);
594

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

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

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

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

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

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

640
    testDriverUnlock(privconn);
641

642 643 644
    return VIR_DRV_OPEN_SUCCESS;

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


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

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

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

C
Cole Robinson 已提交
690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726
static xmlNodePtr
testParseXMLDocFromFile(xmlNodePtr node, const char *file, const char *type)
{
    xmlNodePtr ret = NULL;
    xmlDocPtr doc = NULL;
    char *absFile = NULL;
    char *relFile = virXMLPropString(node, "file");

    if (relFile != NULL) {
        absFile = testBuildFilename(file, relFile);
        VIR_FREE(relFile);
        if (!absFile) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("resolving %s filename"), type);
            return NULL;
        }

        if (!(doc = virXMLParse(absFile, NULL, type)))
            goto error;

        ret = xmlCopyNode(xmlDocGetRootElement(doc), 1);
        if (!ret) {
            virReportOOMError();
            goto error;
        }
        xmlReplaceNode(node, ret);
        xmlFreeNode(node);
    } else {
        ret = node;
    }

error:
    xmlFreeDoc(doc);
    VIR_FREE(absFile);
    return ret;
}

727 728 729
static int
testParseNodeInfo(virNodeInfoPtr nodeInfo, xmlXPathContextPtr ctxt)
{
730
    char *str;
731 732
    long l;
    int ret;
733

734
    ret = virXPathLong("string(/node/cpu/nodes[1])", ctxt, &l);
735 736 737
    if (ret == 0) {
        nodeInfo->nodes = l;
    } else if (ret == -2) {
738 739
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu nodes value"));
740
        goto error;
741
    }
742

743
    ret = virXPathLong("string(/node/cpu/sockets[1])", ctxt, &l);
744 745 746
    if (ret == 0) {
        nodeInfo->sockets = l;
    } else if (ret == -2) {
747 748
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu sockets value"));
749
        goto error;
750
    }
751

752
    ret = virXPathLong("string(/node/cpu/cores[1])", ctxt, &l);
753 754 755
    if (ret == 0) {
        nodeInfo->cores = l;
    } else if (ret == -2) {
756 757
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu cores value"));
758
        goto error;
759 760
    }

761
    ret = virXPathLong("string(/node/cpu/threads[1])", ctxt, &l);
762 763 764
    if (ret == 0) {
        nodeInfo->threads = l;
    } else if (ret == -2) {
765 766
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu threads value"));
767
        goto error;
768
    }
769

770 771
    nodeInfo->cpus = (nodeInfo->cores * nodeInfo->threads *
                      nodeInfo->sockets * nodeInfo->nodes);
772
    ret = virXPathLong("string(/node/cpu/active[1])", ctxt, &l);
773 774
    if (ret == 0) {
        if (l < nodeInfo->cpus) {
775 776
            nodeInfo->cpus = l;
        }
777
    } else if (ret == -2) {
778 779
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu active value"));
780
        goto error;
781
    }
782
    ret = virXPathLong("string(/node/cpu/mhz[1])", ctxt, &l);
783 784 785
    if (ret == 0) {
        nodeInfo->mhz = l;
    } else if (ret == -2) {
786 787
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu mhz value"));
788
        goto error;
789 790
    }

791
    str = virXPathString("string(/node/cpu/model[1])", ctxt);
792
    if (str != NULL) {
C
Chris Lalancette 已提交
793
        if (virStrcpyStatic(nodeInfo->model, str) == NULL) {
794 795
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Model %s too big for destination"), str);
C
Chris Lalancette 已提交
796 797 798
            VIR_FREE(str);
            goto error;
        }
799
        VIR_FREE(str);
800 801
    }

802
    ret = virXPathLong("string(/node/memory[1])", ctxt, &l);
803 804 805
    if (ret == 0) {
        nodeInfo->memory = l;
    } else if (ret == -2) {
806 807
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node memory value"));
808
        goto error;
809
    }
810

811 812 813 814 815 816
    return 0;
error:
    return -1;
}

static int
C
Cole Robinson 已提交
817 818 819
testParseDomains(testConnPtr privconn,
                 const char *file,
                 xmlXPathContextPtr ctxt)
820 821 822 823 824 825 826 827
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virDomainObjPtr obj;

    num = virXPathNodeSet("/node/domain", ctxt, &nodes);
    if (num < 0) {
828
        goto error;
829
    }
830

831
    for (i = 0; i < num; i++) {
832
        virDomainDefPtr def;
C
Cole Robinson 已提交
833 834 835 836 837 838 839 840 841 842
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file, "domain");
        if (!node)
            goto error;

        def = virDomainDefParseNode(ctxt->doc, node,
                                    privconn->caps, privconn->xmlopt,
                                    1 << VIR_DOMAIN_VIRT_TEST,
                                    VIR_DOMAIN_XML_INACTIVE);
        if (!def)
            goto error;
843

844
        if (testDomainGenerateIfnames(def) < 0 ||
845
            !(obj = virDomainObjListAdd(privconn->domains,
846
                                        def,
847
                                        privconn->xmlopt,
848
                                        0, NULL))) {
849
            virDomainDefFree(def);
850 851
            goto error;
        }
852

853
        obj->persistent = 1;
854 855
        if (testDomainStartState(privconn, obj,
                                 VIR_DOMAIN_RUNNING_BOOTED) < 0) {
856
            virObjectUnlock(obj);
857 858 859
            goto error;
        }

860
        virObjectUnlock(obj);
861
    }
862

863 864 865 866 867 868 869
    ret = 0;
error:
    VIR_FREE(nodes);
    return ret;
}

static int
C
Cole Robinson 已提交
870 871 872
testParseNetworks(testConnPtr privconn,
                  const char *file,
                  xmlXPathContextPtr ctxt)
873 874 875 876 877 878 879 880
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virNetworkObjPtr obj;

    num = virXPathNodeSet("/node/network", ctxt, &nodes);
    if (num < 0) {
881 882
        goto error;
    }
883 884

    for (i = 0; i < num; i++) {
885
        virNetworkDefPtr def;
C
Cole Robinson 已提交
886 887 888
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file, "network");
        if (!node)
            goto error;
889

C
Cole Robinson 已提交
890 891 892
        def = virNetworkDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
893 894

        if (!(obj = virNetworkAssignDef(&privconn->networks, def, false))) {
895 896
            virNetworkDefFree(def);
            goto error;
897
        }
898 899 900 901

        obj->persistent = 1;
        obj->active = 1;
        virNetworkObjUnlock(obj);
902
    }
903

904 905 906 907 908 909 910
    ret = 0;
error:
    VIR_FREE(nodes);
    return ret;
}

static int
C
Cole Robinson 已提交
911 912 913
testParseInterfaces(testConnPtr privconn,
                    const char *file,
                    xmlXPathContextPtr ctxt)
914 915 916 917 918 919 920 921
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virInterfaceObjPtr obj;

    num = virXPathNodeSet("/node/interface", ctxt, &nodes);
    if (num < 0) {
L
Laine Stump 已提交
922 923
        goto error;
    }
924 925

    for (i = 0; i < num; i++) {
L
Laine Stump 已提交
926
        virInterfaceDefPtr def;
C
Cole Robinson 已提交
927 928 929 930
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "interface");
        if (!node)
            goto error;
L
Laine Stump 已提交
931

C
Cole Robinson 已提交
932 933 934
        def = virInterfaceDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
935

936
        if (!(obj = virInterfaceAssignDef(&privconn->ifaces, def))) {
L
Laine Stump 已提交
937 938 939
            virInterfaceDefFree(def);
            goto error;
        }
940

941 942 943 944 945 946 947 948 949 950 951
        obj->active = 1;
        virInterfaceObjUnlock(obj);
    }

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

static int
C
Cole Robinson 已提交
952
testOpenVolumesForPool(const char *file,
953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973
                       xmlXPathContextPtr ctxt,
                       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++) {
C
Cole Robinson 已提交
974 975 976 977
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "volume");
        if (!node)
            goto error;
978

C
Cole Robinson 已提交
979 980 981
        def = virStorageVolDefParseNode(pool->def, ctxt->doc, node);
        if (!def)
            goto error;
982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002

        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 已提交
1003 1004
    }

1005 1006 1007 1008 1009 1010 1011 1012
    ret = 0;
error:
    virStorageVolDefFree(def);
    VIR_FREE(nodes);
    return ret;
}

static int
C
Cole Robinson 已提交
1013 1014 1015
testParseStorage(testConnPtr privconn,
                 const char *file,
                 xmlXPathContextPtr ctxt)
1016 1017 1018 1019 1020 1021 1022 1023
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virStoragePoolObjPtr obj;

    num = virXPathNodeSet("/node/pool", ctxt, &nodes);
    if (num < 0) {
C
Cole Robinson 已提交
1024 1025
        goto error;
    }
1026 1027

    for (i = 0; i < num; i++) {
C
Cole Robinson 已提交
1028
        virStoragePoolDefPtr def;
C
Cole Robinson 已提交
1029 1030 1031 1032
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "pool");
        if (!node)
            goto error;
C
Cole Robinson 已提交
1033

C
Cole Robinson 已提交
1034 1035 1036
        def = virStoragePoolDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
C
Cole Robinson 已提交
1037

1038
        if (!(obj = virStoragePoolObjAssignDef(&privconn->pools,
C
Cole Robinson 已提交
1039 1040 1041 1042 1043
                                                def))) {
            virStoragePoolDefFree(def);
            goto error;
        }

1044 1045
        if (testStoragePoolObjSetDefaults(obj) == -1) {
            virStoragePoolObjUnlock(obj);
C
Cole Robinson 已提交
1046
            goto error;
1047
        }
1048
        obj->active = 1;
1049 1050

        /* Find storage volumes */
C
Cole Robinson 已提交
1051
        if (testOpenVolumesForPool(file, ctxt, obj, i+1) < 0) {
1052
            virStoragePoolObjUnlock(obj);
1053 1054 1055
            goto error;
        }

1056
        virStoragePoolObjUnlock(obj);
C
Cole Robinson 已提交
1057 1058
    }

1059 1060 1061 1062 1063 1064 1065
    ret = 0;
error:
    VIR_FREE(nodes);
    return ret;
}

static int
C
Cole Robinson 已提交
1066 1067 1068
testParseNodedevs(testConnPtr privconn,
                  const char *file,
                  xmlXPathContextPtr ctxt)
1069 1070 1071 1072 1073 1074 1075 1076
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virNodeDeviceObjPtr obj;

    num = virXPathNodeSet("/node/device", ctxt, &nodes);
    if (num < 0) {
1077 1078
        goto error;
    }
1079 1080

    for (i = 0; i < num; i++) {
1081
        virNodeDeviceDefPtr def;
C
Cole Robinson 已提交
1082 1083 1084 1085
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                  "nodedev");
        if (!node)
            goto error;
1086

C
Cole Robinson 已提交
1087 1088 1089
        def = virNodeDeviceDefParseNode(ctxt->doc, node, 0, NULL);
        if (!def)
            goto error;
1090 1091

        if (!(obj = virNodeDeviceAssignDef(&privconn->devs, def))) {
1092 1093 1094
            virNodeDeviceDefFree(def);
            goto error;
        }
1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118

        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;
1119 1120
    }

1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150
    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;
C
Cole Robinson 已提交
1151
    if (testParseDomains(privconn, file, ctxt) < 0)
1152
        goto error;
C
Cole Robinson 已提交
1153
    if (testParseNetworks(privconn, file, ctxt) < 0)
1154
        goto error;
C
Cole Robinson 已提交
1155
    if (testParseInterfaces(privconn, file, ctxt) < 0)
1156
        goto error;
C
Cole Robinson 已提交
1157
    if (testParseStorage(privconn, file, ctxt) < 0)
1158
        goto error;
C
Cole Robinson 已提交
1159
    if (testParseNodedevs(privconn, file, ctxt) < 0)
1160
        goto error;
1161

J
Jim Meyering 已提交
1162
    xmlXPathFreeContext(ctxt);
1163
    xmlFreeDoc(doc);
1164
    testDriverUnlock(privconn);
1165

1166
    return 0;
1167 1168

 error:
J
Jim Meyering 已提交
1169
    xmlXPathFreeContext(ctxt);
1170
    xmlFreeDoc(doc);
1171
    virObjectUnref(privconn->domains);
1172
    virNetworkObjListFree(&privconn->networks);
L
Laine Stump 已提交
1173
    virInterfaceObjListFree(&privconn->ifaces);
C
Cole Robinson 已提交
1174
    virStoragePoolObjListFree(&privconn->pools);
E
Eric Blake 已提交
1175
    VIR_FREE(privconn->path);
1176
    testDriverUnlock(privconn);
1177
    VIR_FREE(privconn);
1178
    conn->privateData = NULL;
1179
    return VIR_DRV_OPEN_ERROR;
1180 1181
}

1182

1183 1184 1185
static virDrvOpenStatus testConnectOpen(virConnectPtr conn,
                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                        unsigned int flags)
1186
{
1187
    int ret;
1188
    testConnPtr privconn;
1189

E
Eric Blake 已提交
1190 1191
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

1192
    if (!conn->uri)
1193
        return VIR_DRV_OPEN_DECLINED;
1194

1195
    if (!conn->uri->scheme || STRNEQ(conn->uri->scheme, "test"))
1196
        return VIR_DRV_OPEN_DECLINED;
1197

1198
    /* Remote driver should handle these. */
1199
    if (conn->uri->server)
1200 1201
        return VIR_DRV_OPEN_DECLINED;

1202
    /* From this point on, the connection is for us. */
1203 1204 1205
    if (!conn->uri->path
        || conn->uri->path[0] == '\0'
        || (conn->uri->path[0] == '/' && conn->uri->path[1] == '\0')) {
1206 1207
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("testOpen: supply a path or use test:///default"));
1208 1209
        return VIR_DRV_OPEN_ERROR;
    }
1210

1211
    if (STREQ(conn->uri->path, "/default"))
1212 1213
        ret = testOpenDefault(conn);
    else
1214
        ret = testOpenFromFile(conn,
1215
                               conn->uri->path);
1216

1217 1218 1219 1220 1221
    if (ret != VIR_DRV_OPEN_SUCCESS)
        return ret;

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

1223
    privconn->domainEventState = virDomainEventStateNew();
1224
    if (!privconn->domainEventState) {
1225
        testDriverUnlock(privconn);
1226
        testConnectClose(conn);
1227
        return VIR_DRV_OPEN_ERROR;
1228 1229
    }

1230 1231 1232
    testDriverUnlock(privconn);

    return VIR_DRV_OPEN_SUCCESS;
1233 1234
}

1235
static int testConnectClose(virConnectPtr conn)
1236
{
1237
    testConnPtr privconn = conn->privateData;
1238
    testDriverLock(privconn);
1239
    virObjectUnref(privconn->caps);
1240
    virObjectUnref(privconn->xmlopt);
1241
    virObjectUnref(privconn->domains);
D
Daniel P. Berrange 已提交
1242
    virNodeDeviceObjListFree(&privconn->devs);
1243
    virNetworkObjListFree(&privconn->networks);
L
Laine Stump 已提交
1244
    virInterfaceObjListFree(&privconn->ifaces);
C
Cole Robinson 已提交
1245
    virStoragePoolObjListFree(&privconn->pools);
1246
    virDomainEventStateFree(privconn->domainEventState);
E
Eric Blake 已提交
1247
    VIR_FREE(privconn->path);
1248

1249
    testDriverUnlock(privconn);
1250
    virMutexDestroy(&privconn->lock);
1251

1252
    VIR_FREE(privconn);
1253
    conn->privateData = NULL;
1254
    return 0;
1255 1256
}

1257 1258
static int testConnectGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
                                 unsigned long *hvVer)
1259
{
1260
    *hvVer = 2;
1261
    return 0;
1262 1263
}

1264 1265 1266 1267 1268 1269
static char *testConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return virGetHostname();
}


1270
static int testConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
1271 1272 1273 1274
{
    return 1;
}

1275
static int testConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
1276 1277 1278 1279
{
    return 0;
}

1280
static int testConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
1281 1282 1283 1284
{
    return 1;
}

1285 1286
static int testConnectGetMaxVcpus(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type ATTRIBUTE_UNUSED)
1287 1288 1289 1290 1291 1292
{
    return 32;
}

static int testNodeGetInfo(virConnectPtr conn,
                           virNodeInfoPtr info)
1293
{
1294
    testConnPtr privconn = conn->privateData;
1295
    testDriverLock(privconn);
1296
    memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo));
1297
    testDriverUnlock(privconn);
1298
    return 0;
1299 1300
}

1301
static char *testConnectGetCapabilities(virConnectPtr conn)
1302
{
1303
    testConnPtr privconn = conn->privateData;
1304
    char *xml;
1305
    testDriverLock(privconn);
1306
    if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL)
1307
        virReportOOMError();
1308
    testDriverUnlock(privconn);
1309
    return xml;
1310 1311
}

1312
static int testConnectNumOfDomains(virConnectPtr conn)
1313
{
1314
    testConnPtr privconn = conn->privateData;
1315
    int count;
1316

1317
    testDriverLock(privconn);
1318
    count = virDomainObjListNumOfDomains(privconn->domains, true, NULL, NULL);
1319
    testDriverUnlock(privconn);
1320

1321
    return count;
1322 1323
}

1324 1325 1326 1327 1328 1329 1330
static int testDomainIsActive(virDomainPtr dom)
{
    testConnPtr privconn = dom->conn->privateData;
    virDomainObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
1331
    obj = virDomainObjListFindByUUID(privconn->domains, dom->uuid);
1332 1333
    testDriverUnlock(privconn);
    if (!obj) {
1334
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1335 1336 1337 1338 1339 1340
        goto cleanup;
    }
    ret = virDomainObjIsActive(obj);

cleanup:
    if (obj)
1341
        virObjectUnlock(obj);
1342 1343 1344 1345 1346 1347 1348 1349 1350 1351
    return ret;
}

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

    testDriverLock(privconn);
1352
    obj = virDomainObjListFindByUUID(privconn->domains, dom->uuid);
1353 1354
    testDriverUnlock(privconn);
    if (!obj) {
1355
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1356 1357 1358 1359 1360 1361
        goto cleanup;
    }
    ret = obj->persistent;

cleanup:
    if (obj)
1362
        virObjectUnlock(obj);
1363 1364 1365
    return ret;
}

1366 1367 1368 1369 1370
static int testDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
{
    return 0;
}

1371
static virDomainPtr
1372
testDomainCreateXML(virConnectPtr conn, const char *xml,
1373
                      unsigned int flags)
1374
{
1375
    testConnPtr privconn = conn->privateData;
1376
    virDomainPtr ret = NULL;
1377
    virDomainDefPtr def;
1378
    virDomainObjPtr dom = NULL;
1379
    virDomainEventPtr event = NULL;
1380

1381 1382
    virCheckFlags(0, NULL);

1383
    testDriverLock(privconn);
1384 1385
    if ((def = virDomainDefParseString(xml,privconn->caps, privconn->xmlopt,
                                       1 << VIR_DOMAIN_VIRT_TEST,
1386
                                       VIR_DOMAIN_XML_INACTIVE)) == NULL)
1387
        goto cleanup;
1388

1389
    if (testDomainGenerateIfnames(def) < 0)
1390
        goto cleanup;
1391
    if (!(dom = virDomainObjListAdd(privconn->domains,
1392
                                    def,
1393
                                    privconn->xmlopt,
1394 1395
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
1396 1397
        goto cleanup;
    def = NULL;
1398

1399
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_BOOTED) < 0)
1400
        goto cleanup;
1401

1402 1403 1404 1405
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);

1406
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1407
    if (ret)
1408
        ret->id = dom->def->id;
1409 1410

cleanup:
1411
    if (dom)
1412
        virObjectUnlock(dom);
1413 1414
    if (event)
        testDomainEventQueue(privconn, event);
1415
    virDomainDefFree(def);
1416
    testDriverUnlock(privconn);
1417
    return ret;
1418 1419 1420
}


1421
static virDomainPtr testDomainLookupByID(virConnectPtr conn,
1422
                                         int id)
1423
{
1424
    testConnPtr privconn = conn->privateData;
1425 1426
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1427

1428
    testDriverLock(privconn);
1429
    dom = virDomainObjListFindByID(privconn->domains, id);
1430 1431 1432
    testDriverUnlock(privconn);

    if (dom == NULL) {
1433
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1434
        goto cleanup;
1435 1436
    }

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

cleanup:
1442
    if (dom)
1443
        virObjectUnlock(dom);
1444
    return ret;
1445 1446
}

1447
static virDomainPtr testDomainLookupByUUID(virConnectPtr conn,
1448
                                           const unsigned char *uuid)
1449
{
1450
    testConnPtr privconn = conn->privateData;
1451
    virDomainPtr ret = NULL;
1452
    virDomainObjPtr dom;
1453

1454
    testDriverLock(privconn);
1455
    dom = virDomainObjListFindByUUID(privconn->domains, uuid);
1456 1457 1458
    testDriverUnlock(privconn);

    if (dom == NULL) {
1459
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1460
        goto cleanup;
1461
    }
1462

1463
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1464 1465 1466 1467
    if (ret)
        ret->id = dom->def->id;

cleanup:
1468
    if (dom)
1469
        virObjectUnlock(dom);
1470
    return ret;
1471 1472
}

1473
static virDomainPtr testDomainLookupByName(virConnectPtr conn,
1474
                                           const char *name)
1475
{
1476
    testConnPtr privconn = conn->privateData;
1477 1478
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1479

1480
    testDriverLock(privconn);
1481
    dom = virDomainObjListFindByName(privconn->domains, name);
1482 1483 1484
    testDriverUnlock(privconn);

    if (dom == NULL) {
1485
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1486
        goto cleanup;
1487
    }
1488

1489
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1490 1491 1492 1493
    if (ret)
        ret->id = dom->def->id;

cleanup:
1494
    if (dom)
1495
        virObjectUnlock(dom);
1496
    return ret;
1497 1498
}

1499 1500 1501
static int testConnectListDomains(virConnectPtr conn,
                                  int *ids,
                                  int maxids)
1502
{
1503
    testConnPtr privconn = conn->privateData;
1504
    int n;
1505

1506
    testDriverLock(privconn);
1507
    n = virDomainObjListGetActiveIDs(privconn->domains, ids, maxids, NULL, NULL);
1508
    testDriverUnlock(privconn);
1509

1510
    return n;
1511 1512
}

1513
static int testDomainDestroy(virDomainPtr domain)
1514
{
1515 1516
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1517
    virDomainEventPtr event = NULL;
1518
    int ret = -1;
1519

1520
    testDriverLock(privconn);
1521 1522
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1523 1524

    if (privdom == NULL) {
1525
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1526
        goto cleanup;
1527
    }
1528

J
Jiri Denemark 已提交
1529
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_DESTROYED);
1530 1531 1532
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
1533

1534
    if (!privdom->persistent) {
1535 1536
        virDomainObjListRemove(privconn->domains,
                               privdom);
1537
        privdom = NULL;
1538
    }
1539 1540 1541

    ret = 0;
cleanup:
1542
    if (privdom)
1543
        virObjectUnlock(privdom);
1544 1545
    if (event)
        testDomainEventQueue(privconn, event);
1546
    testDriverUnlock(privconn);
1547
    return ret;
1548 1549
}

1550
static int testDomainResume(virDomainPtr domain)
1551
{
1552 1553
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1554
    virDomainEventPtr event = NULL;
1555
    int ret = -1;
1556

1557
    testDriverLock(privconn);
1558 1559
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1560
    testDriverUnlock(privconn);
1561 1562

    if (privdom == NULL) {
1563
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1564
        goto cleanup;
1565
    }
1566

J
Jiri Denemark 已提交
1567
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_PAUSED) {
1568 1569
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"),
                       domain->name);
1570
        goto cleanup;
1571
    }
1572

J
Jiri Denemark 已提交
1573 1574
    virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                         VIR_DOMAIN_RUNNING_UNPAUSED);
1575 1576 1577
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_RESUMED,
                                     VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
1578 1579 1580
    ret = 0;

cleanup:
1581
    if (privdom)
1582
        virObjectUnlock(privdom);
1583 1584 1585 1586 1587
    if (event) {
        testDriverLock(privconn);
        testDomainEventQueue(privconn, event);
        testDriverUnlock(privconn);
    }
1588
    return ret;
1589 1590
}

1591
static int testDomainSuspend(virDomainPtr domain)
1592
{
1593 1594
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1595
    virDomainEventPtr event = NULL;
1596
    int ret = -1;
J
Jiri Denemark 已提交
1597
    int state;
1598

1599
    testDriverLock(privconn);
1600 1601
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1602
    testDriverUnlock(privconn);
1603 1604

    if (privdom == NULL) {
1605
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1606
        goto cleanup;
1607
    }
1608

J
Jiri Denemark 已提交
1609 1610
    state = virDomainObjGetState(privdom, NULL);
    if (state == VIR_DOMAIN_SHUTOFF || state == VIR_DOMAIN_PAUSED) {
1611 1612
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"),
                       domain->name);
1613
        goto cleanup;
1614
    }
1615

J
Jiri Denemark 已提交
1616
    virDomainObjSetState(privdom, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
1617 1618 1619
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_SUSPENDED,
                                     VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
1620 1621 1622
    ret = 0;

cleanup:
1623
    if (privdom)
1624
        virObjectUnlock(privdom);
1625 1626 1627 1628 1629 1630

    if (event) {
        testDriverLock(privconn);
        testDomainEventQueue(privconn, event);
        testDriverUnlock(privconn);
    }
1631
    return ret;
1632 1633
}

1634
static int testDomainShutdownFlags(virDomainPtr domain,
1635
                                   unsigned int flags)
1636
{
1637 1638
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1639
    virDomainEventPtr event = NULL;
1640
    int ret = -1;
1641

1642 1643
    virCheckFlags(0, -1);

1644
    testDriverLock(privconn);
1645 1646
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1647 1648

    if (privdom == NULL) {
1649
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1650
        goto cleanup;
1651
    }
1652

J
Jiri Denemark 已提交
1653
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
1654 1655
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("domain '%s' not running"), domain->name);
1656
        goto cleanup;
1657
    }
1658

J
Jiri Denemark 已提交
1659
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1660 1661 1662
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1663

1664
    if (!privdom->persistent) {
1665 1666
        virDomainObjListRemove(privconn->domains,
                               privdom);
1667 1668
        privdom = NULL;
    }
1669

1670
    ret = 0;
1671
cleanup:
1672
    if (privdom)
1673
        virObjectUnlock(privdom);
1674 1675
    if (event)
        testDomainEventQueue(privconn, event);
1676
    testDriverUnlock(privconn);
1677
    return ret;
1678 1679
}

1680
static int testDomainShutdown(virDomainPtr domain)
1681
{
1682
    return testDomainShutdownFlags(domain, 0);
1683 1684
}

1685
/* Similar behaviour as shutdown */
1686
static int testDomainReboot(virDomainPtr domain,
1687
                            unsigned int action ATTRIBUTE_UNUSED)
1688
{
1689 1690
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1691
    virDomainEventPtr event = NULL;
1692
    int ret = -1;
1693

1694
    testDriverLock(privconn);
1695 1696
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1697 1698

    if (privdom == NULL) {
1699
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1700
        goto cleanup;
1701
    }
1702

J
Jiri Denemark 已提交
1703 1704 1705
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTDOWN,
                         VIR_DOMAIN_SHUTDOWN_USER);

1706 1707
    switch (privdom->def->onReboot) {
    case VIR_DOMAIN_LIFECYCLE_DESTROY:
J
Jiri Denemark 已提交
1708 1709
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1710 1711
        break;

1712
    case VIR_DOMAIN_LIFECYCLE_RESTART:
J
Jiri Denemark 已提交
1713 1714
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
1715 1716
        break;

1717
    case VIR_DOMAIN_LIFECYCLE_PRESERVE:
J
Jiri Denemark 已提交
1718 1719
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1720 1721
        break;

1722
    case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME:
J
Jiri Denemark 已提交
1723 1724
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
1725
        break;
1726

1727
    default:
J
Jiri Denemark 已提交
1728 1729
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1730 1731
        break;
    }
1732

J
Jiri Denemark 已提交
1733 1734
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1735 1736 1737
        event = virDomainEventNewFromObj(privdom,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1738

1739
        if (!privdom->persistent) {
1740 1741
            virDomainObjListRemove(privconn->domains,
                                   privdom);
1742 1743
            privdom = NULL;
        }
1744 1745
    }

1746 1747
    ret = 0;
cleanup:
1748
    if (privdom)
1749
        virObjectUnlock(privdom);
1750 1751
    if (event)
        testDomainEventQueue(privconn, event);
1752
    testDriverUnlock(privconn);
1753
    return ret;
1754 1755
}

1756
static int testDomainGetInfo(virDomainPtr domain,
1757
                             virDomainInfoPtr info)
1758
{
1759
    testConnPtr privconn = domain->conn->privateData;
1760
    struct timeval tv;
1761
    virDomainObjPtr privdom;
1762
    int ret = -1;
1763

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

    if (privdom == NULL) {
1770
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1771
        goto cleanup;
1772
    }
1773 1774

    if (gettimeofday(&tv, NULL) < 0) {
1775 1776
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("getting time of day"));
1777
        goto cleanup;
1778 1779
    }

J
Jiri Denemark 已提交
1780
    info->state = virDomainObjGetState(privdom, NULL);
1781 1782
    info->memory = privdom->def->mem.cur_balloon;
    info->maxMem = privdom->def->mem.max_balloon;
1783 1784
    info->nrVirtCpu = privdom->def->vcpus;
    info->cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
1785 1786 1787
    ret = 0;

cleanup:
1788
    if (privdom)
1789
        virObjectUnlock(privdom);
1790
    return ret;
1791 1792
}

1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805
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);
1806 1807
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1808 1809 1810
    testDriverUnlock(privconn);

    if (privdom == NULL) {
1811
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1812 1813 1814
        goto cleanup;
    }

J
Jiri Denemark 已提交
1815
    *state = virDomainObjGetState(privdom, reason);
1816 1817 1818 1819
    ret = 0;

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

1824 1825
#define TEST_SAVE_MAGIC "TestGuestMagic"

1826 1827 1828
static int
testDomainSaveFlags(virDomainPtr domain, const char *path,
                    const char *dxml, unsigned int flags)
1829
{
1830
    testConnPtr privconn = domain->conn->privateData;
1831 1832 1833
    char *xml = NULL;
    int fd = -1;
    int len;
1834
    virDomainObjPtr privdom;
1835
    virDomainEventPtr event = NULL;
1836
    int ret = -1;
1837

1838 1839
    virCheckFlags(0, -1);
    if (dxml) {
1840 1841
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1842 1843 1844
        return -1;
    }

1845
    testDriverLock(privconn);
1846 1847
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1848 1849

    if (privdom == NULL) {
1850
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1851
        goto cleanup;
1852
    }
1853

1854
    xml = virDomainDefFormat(privdom->def,
C
Cole Robinson 已提交
1855 1856
                             VIR_DOMAIN_XML_SECURE);

1857
    if (xml == NULL) {
1858
        virReportSystemError(errno,
1859 1860
                             _("saving domain '%s' failed to allocate space for metadata"),
                             domain->name);
1861
        goto cleanup;
1862
    }
1863 1864

    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
1865
        virReportSystemError(errno,
1866 1867
                             _("saving domain '%s' to '%s': open failed"),
                             domain->name, path);
1868
        goto cleanup;
1869
    }
1870
    len = strlen(xml);
1871
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
1872
        virReportSystemError(errno,
1873 1874
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1875
        goto cleanup;
1876
    }
1877
    if (safewrite(fd, (char*)&len, sizeof(len)) < 0) {
1878
        virReportSystemError(errno,
1879 1880
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1881
        goto cleanup;
1882
    }
1883
    if (safewrite(fd, xml, len) < 0) {
1884
        virReportSystemError(errno,
1885 1886
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1887
        goto cleanup;
1888
    }
1889

1890
    if (VIR_CLOSE(fd) < 0) {
1891
        virReportSystemError(errno,
1892 1893
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1894
        goto cleanup;
1895
    }
1896 1897
    fd = -1;

J
Jiri Denemark 已提交
1898
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SAVED);
1899 1900 1901
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
1902

1903
    if (!privdom->persistent) {
1904 1905
        virDomainObjListRemove(privconn->domains,
                               privdom);
1906
        privdom = NULL;
1907
    }
1908

1909
    ret = 0;
1910 1911 1912 1913 1914 1915 1916
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) {
1917
        VIR_FORCE_CLOSE(fd);
1918 1919
        unlink(path);
    }
1920
    if (privdom)
1921
        virObjectUnlock(privdom);
1922 1923
    if (event)
        testDomainEventQueue(privconn, event);
1924
    testDriverUnlock(privconn);
1925
    return ret;
1926 1927
}

1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939
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)
1940
{
1941
    testConnPtr privconn = conn->privateData;
1942
    char *xml = NULL;
1943
    char magic[15];
1944 1945 1946
    int fd = -1;
    int len;
    virDomainDefPtr def = NULL;
1947
    virDomainObjPtr dom = NULL;
1948
    virDomainEventPtr event = NULL;
1949
    int ret = -1;
1950

1951 1952
    virCheckFlags(0, -1);
    if (dxml) {
1953 1954
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1955 1956 1957
        return -1;
    }

1958 1959
    testDriverLock(privconn);

1960
    if ((fd = open(path, O_RDONLY)) < 0) {
1961
        virReportSystemError(errno,
1962 1963
                             _("cannot read domain image '%s'"),
                             path);
1964
        goto cleanup;
1965
    }
1966
    if (saferead(fd, magic, sizeof(magic)) != sizeof(magic)) {
1967
        virReportSystemError(errno,
1968 1969
                             _("incomplete save header in '%s'"),
                             path);
1970
        goto cleanup;
1971
    }
1972
    if (memcmp(magic, TEST_SAVE_MAGIC, sizeof(magic))) {
1973 1974
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("mismatched header magic"));
1975
        goto cleanup;
1976
    }
1977
    if (saferead(fd, (char*)&len, sizeof(len)) != sizeof(len)) {
1978
        virReportSystemError(errno,
1979 1980
                             _("failed to read metadata length in '%s'"),
                             path);
1981
        goto cleanup;
1982 1983
    }
    if (len < 1 || len > 8192) {
1984 1985
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("length of metadata out of range"));
1986
        goto cleanup;
1987
    }
1988
    if (VIR_ALLOC_N(xml, len+1) < 0)
1989
        goto cleanup;
1990
    if (saferead(fd, xml, len) != len) {
1991
        virReportSystemError(errno,
1992
                             _("incomplete metdata in '%s'"), path);
1993
        goto cleanup;
1994 1995
    }
    xml[len] = '\0';
1996

1997 1998
    def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
                                  1 << VIR_DOMAIN_VIRT_TEST,
1999
                                  VIR_DOMAIN_XML_INACTIVE);
2000
    if (!def)
2001
        goto cleanup;
2002

2003
    if (testDomainGenerateIfnames(def) < 0)
2004
        goto cleanup;
2005
    if (!(dom = virDomainObjListAdd(privconn->domains,
2006
                                    def,
2007
                                    privconn->xmlopt,
2008 2009 2010
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
2011 2012
        goto cleanup;
    def = NULL;
2013

2014
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_RESTORED) < 0)
2015 2016
        goto cleanup;

2017 2018 2019
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
2020
    ret = 0;
2021 2022 2023 2024

cleanup:
    virDomainDefFree(def);
    VIR_FREE(xml);
2025
    VIR_FORCE_CLOSE(fd);
2026
    if (dom)
2027
        virObjectUnlock(dom);
2028 2029
    if (event)
        testDomainEventQueue(privconn, event);
2030
    testDriverUnlock(privconn);
2031
    return ret;
2032 2033
}

2034 2035 2036 2037 2038 2039 2040
static int
testDomainRestore(virConnectPtr conn,
                  const char *path)
{
    return testDomainRestoreFlags(conn, path, NULL, 0);
}

2041 2042
static int testDomainCoreDump(virDomainPtr domain,
                              const char *to,
E
Eric Blake 已提交
2043
                              unsigned int flags)
2044
{
2045
    testConnPtr privconn = domain->conn->privateData;
2046
    int fd = -1;
2047
    virDomainObjPtr privdom;
2048
    virDomainEventPtr event = NULL;
2049
    int ret = -1;
2050

E
Eric Blake 已提交
2051 2052
    virCheckFlags(VIR_DUMP_CRASH, -1);

2053
    testDriverLock(privconn);
2054 2055
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2056 2057

    if (privdom == NULL) {
2058
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2059
        goto cleanup;
2060
    }
2061 2062

    if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
2063
        virReportSystemError(errno,
2064 2065
                             _("domain '%s' coredump: failed to open %s"),
                             domain->name, to);
2066
        goto cleanup;
2067
    }
2068
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
2069
        virReportSystemError(errno,
2070 2071
                             _("domain '%s' coredump: failed to write header to %s"),
                             domain->name, to);
2072
        goto cleanup;
2073
    }
2074
    if (VIR_CLOSE(fd) < 0) {
2075
        virReportSystemError(errno,
2076 2077
                             _("domain '%s' coredump: write failed: %s"),
                             domain->name, to);
2078
        goto cleanup;
2079
    }
2080

2081
    if (flags & VIR_DUMP_CRASH) {
J
Jiri Denemark 已提交
2082
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_CRASHED);
2083 2084 2085 2086
        event = virDomainEventNewFromObj(privdom,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
        if (!privdom->persistent) {
2087 2088
            virDomainObjListRemove(privconn->domains,
                                   privdom);
2089 2090
            privdom = NULL;
        }
2091
    }
2092

2093
    ret = 0;
2094
cleanup:
2095
    VIR_FORCE_CLOSE(fd);
2096
    if (privdom)
2097
        virObjectUnlock(privdom);
2098 2099
    if (event)
        testDomainEventQueue(privconn, event);
2100
    testDriverUnlock(privconn);
2101
    return ret;
2102 2103
}

2104
static char *testDomainGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) {
2105 2106 2107
    char *ret;

    ignore_value(VIR_STRDUP(ret, "linux"));
2108
    return ret;
2109 2110
}

2111
static unsigned long long testDomainGetMaxMemory(virDomainPtr domain) {
2112 2113
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2114
    unsigned long long ret = 0;
2115

2116
    testDriverLock(privconn);
2117 2118
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2119
    testDriverUnlock(privconn);
2120 2121

    if (privdom == NULL) {
2122
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2123
        goto cleanup;
2124
    }
2125

2126
    ret = privdom->def->mem.max_balloon;
2127 2128

cleanup:
2129
    if (privdom)
2130
        virObjectUnlock(privdom);
2131
    return ret;
2132 2133
}

2134 2135
static int testDomainSetMaxMemory(virDomainPtr domain,
                                  unsigned long memory)
2136
{
2137 2138
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2139
    int ret = -1;
2140

2141
    testDriverLock(privconn);
2142 2143
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2144
    testDriverUnlock(privconn);
2145 2146

    if (privdom == NULL) {
2147
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2148
        goto cleanup;
2149
    }
2150 2151

    /* XXX validate not over host memory wrt to other domains */
2152
    privdom->def->mem.max_balloon = memory;
2153 2154 2155
    ret = 0;

cleanup:
2156
    if (privdom)
2157
        virObjectUnlock(privdom);
2158
    return ret;
2159 2160
}

2161 2162
static int testDomainSetMemory(virDomainPtr domain,
                               unsigned long memory)
2163
{
2164 2165
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2166
    int ret = -1;
2167

2168
    testDriverLock(privconn);
2169 2170
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2171
    testDriverUnlock(privconn);
2172 2173

    if (privdom == NULL) {
2174
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2175
        goto cleanup;
2176
    }
2177

2178
    if (memory > privdom->def->mem.max_balloon) {
2179
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2180
        goto cleanup;
2181
    }
2182

2183
    privdom->def->mem.cur_balloon = memory;
2184 2185 2186
    ret = 0;

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

2192 2193
static int
testDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
C
Cole Robinson 已提交
2194
{
2195 2196 2197 2198 2199
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr vm;
    virDomainDefPtr def;
    int ret = -1;

2200 2201
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2202 2203 2204
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

    testDriverLock(privconn);
2205
    vm = virDomainObjListFindByUUID(privconn->domains, domain->uuid);
2206 2207 2208 2209 2210
    testDriverUnlock(privconn);

    if (!vm) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(domain->uuid, uuidstr);
2211 2212
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching uuid '%s'"), uuidstr);
2213 2214 2215
        goto cleanup;
    }

2216
    if (virDomainLiveConfigHelperMethod(privconn->caps, privconn->xmlopt,
2217
                                        vm, &flags, &def) < 0)
2218
        goto cleanup;
2219

2220
    if (flags & VIR_DOMAIN_AFFECT_LIVE)
2221 2222 2223 2224 2225 2226
        def = vm->def;

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

cleanup:
    if (vm)
2227
        virObjectUnlock(vm);
2228
    return ret;
C
Cole Robinson 已提交
2229 2230
}

2231 2232 2233
static int
testDomainGetMaxVcpus(virDomainPtr domain)
{
2234
    return testDomainGetVcpusFlags(domain, (VIR_DOMAIN_AFFECT_LIVE |
2235 2236 2237 2238 2239 2240 2241
                                            VIR_DOMAIN_VCPU_MAXIMUM));
}

static int
testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
                        unsigned int flags)
{
2242
    testConnPtr privconn = domain->conn->privateData;
2243
    virDomainObjPtr privdom = NULL;
2244
    virDomainDefPtr persistentDef;
C
Cole Robinson 已提交
2245 2246
    int ret = -1, maxvcpus;

2247 2248
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2249 2250 2251 2252
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

    /* At least one of LIVE or CONFIG must be set.  MAXIMUM cannot be
     * mixed with LIVE.  */
2253 2254 2255
    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)) {
2256 2257
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
2258 2259
        return -1;
    }
2260
    if (!nrCpus || (maxvcpus = testConnectGetMaxVcpus(domain->conn, NULL)) < nrCpus) {
2261 2262
        virReportError(VIR_ERR_INVALID_ARG,
                       _("argument out of range: %d"), nrCpus);
2263 2264
        return -1;
    }
2265

2266
    testDriverLock(privconn);
2267
    privdom = virDomainObjListFindByUUID(privconn->domains, domain->uuid);
2268 2269 2270
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2271
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2272
        goto cleanup;
2273
    }
2274

2275
    if (!virDomainObjIsActive(privdom) && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
2276 2277
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot hotplug vcpus for an inactive domain"));
C
Cole Robinson 已提交
2278 2279 2280
        goto cleanup;
    }

2281 2282
    /* We allow more cpus in guest than host, but not more than the
     * domain's starting limit.  */
C
Cole Robinson 已提交
2283 2284
    if (!(flags & (VIR_DOMAIN_VCPU_MAXIMUM)) &&
        privdom->def->maxvcpus < maxvcpus)
2285
        maxvcpus = privdom->def->maxvcpus;
C
Cole Robinson 已提交
2286

C
Cole Robinson 已提交
2287
    if (nrCpus > maxvcpus) {
2288 2289 2290
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested cpu amount exceeds maximum (%d > %d)"),
                       nrCpus, maxvcpus);
2291
        goto cleanup;
2292
    }
2293

2294
    if (!(persistentDef = virDomainObjGetPersistentDef(privconn->caps,
2295
                                                       privconn->xmlopt,
2296 2297 2298
                                                       privdom)))
        goto cleanup;

2299
    switch (flags) {
2300
    case VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_AFFECT_CONFIG:
2301 2302 2303
        persistentDef->maxvcpus = nrCpus;
        if (nrCpus < persistentDef->vcpus)
            persistentDef->vcpus = nrCpus;
2304 2305
        ret = 0;
        break;
2306

2307
    case VIR_DOMAIN_AFFECT_CONFIG:
2308
        persistentDef->vcpus = nrCpus;
2309 2310 2311
        ret = 0;
        break;

2312
    case VIR_DOMAIN_AFFECT_LIVE:
2313
        ret = testDomainUpdateVCPUs(privconn, privdom, nrCpus, 0);
2314 2315
        break;

2316
    case VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG:
2317
        ret = testDomainUpdateVCPUs(privconn, privdom, nrCpus, 0);
2318 2319 2320
        if (ret == 0) {
            persistentDef->vcpus = nrCpus;
        }
2321 2322
        break;
    }
2323 2324

cleanup:
2325
    if (privdom)
2326
        virObjectUnlock(privdom);
2327
    return ret;
2328 2329
}

2330
static int
2331
testDomainSetVcpus(virDomainPtr domain, unsigned int nrCpus)
2332
{
2333
    return testDomainSetVcpusFlags(domain, nrCpus, VIR_DOMAIN_AFFECT_LIVE);
2334 2335
}

C
Cole Robinson 已提交
2336 2337 2338 2339 2340 2341 2342 2343 2344
static int testDomainGetVcpus(virDomainPtr domain,
                              virVcpuInfoPtr info,
                              int maxinfo,
                              unsigned char *cpumaps,
                              int maplen)
{
    testConnPtr privconn = domain->conn->privateData;
    testDomainObjPrivatePtr privdomdata;
    virDomainObjPtr privdom;
2345 2346
    size_t i;
    int v, maxcpu, hostcpus;
C
Cole Robinson 已提交
2347 2348 2349 2350 2351
    int ret = -1;
    struct timeval tv;
    unsigned long long statbase;

    testDriverLock(privconn);
2352
    privdom = virDomainObjListFindByName(privconn->domains, domain->name);
C
Cole Robinson 已提交
2353 2354 2355
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2356
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
C
Cole Robinson 已提交
2357 2358 2359 2360
        goto cleanup;
    }

    if (!virDomainObjIsActive(privdom)) {
2361 2362
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s",_("cannot list vcpus for an inactive domain"));
C
Cole Robinson 已提交
2363 2364 2365 2366 2367 2368
        goto cleanup;
    }

    privdomdata = privdom->privateData;

    if (gettimeofday(&tv, NULL) < 0) {
2369
        virReportSystemError(errno,
C
Cole Robinson 已提交
2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389
                             "%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);

2390
        for (i = 0; i < maxinfo; i++) {
C
Cole Robinson 已提交
2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406
            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);

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

2410
            for (i = 0; i < maxcpu; i++) {
C
Cole Robinson 已提交
2411 2412 2413 2414 2415 2416 2417 2418 2419 2420
                if (VIR_CPU_USABLE(privdomdata->cpumaps, privmaplen, v, i)) {
                    VIR_USE_CPU(cpumap, i);
                }
            }
        }
    }

    ret = maxinfo;
cleanup:
    if (privdom)
2421
        virObjectUnlock(privdom);
C
Cole Robinson 已提交
2422 2423 2424
    return ret;
}

C
Cole Robinson 已提交
2425 2426 2427 2428 2429 2430 2431 2432 2433
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;
2434 2435
    size_t i;
    int maxcpu, hostcpus, privmaplen;
C
Cole Robinson 已提交
2436 2437 2438
    int ret = -1;

    testDriverLock(privconn);
2439
    privdom = virDomainObjListFindByName(privconn->domains, domain->name);
C
Cole Robinson 已提交
2440 2441 2442
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2443
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
C
Cole Robinson 已提交
2444 2445 2446 2447
        goto cleanup;
    }

    if (!virDomainObjIsActive(privdom)) {
2448 2449
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s",_("cannot pin vcpus on an inactive domain"));
C
Cole Robinson 已提交
2450 2451 2452 2453
        goto cleanup;
    }

    if (vcpu > privdom->def->vcpus) {
2454 2455
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("requested vcpu is higher than allocated vcpus"));
C
Cole Robinson 已提交
2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469
        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);

2470
    for (i = 0; i < maxcpu; i++) {
C
Cole Robinson 已提交
2471 2472 2473 2474 2475 2476 2477 2478
        if (VIR_CPU_USABLE(cpumap, maplen, 0, i)) {
            VIR_USE_CPU(privcpumap, i);
        }
    }

    ret = 0;
cleanup:
    if (privdom)
2479
        virObjectUnlock(privdom);
C
Cole Robinson 已提交
2480 2481 2482
    return ret;
}

2483
static char *testDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
2484
{
2485
    testConnPtr privconn = domain->conn->privateData;
2486
    virDomainDefPtr def;
2487
    virDomainObjPtr privdom;
2488 2489
    char *ret = NULL;

2490 2491
    /* Flags checked by virDomainDefFormat */

2492
    testDriverLock(privconn);
2493 2494
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2495 2496 2497
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2498
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2499
        goto cleanup;
2500
    }
2501

2502 2503
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
2504

2505
    ret = virDomainDefFormat(def,
2506 2507 2508
                             flags);

cleanup:
2509
    if (privdom)
2510
        virObjectUnlock(privdom);
2511
    return ret;
2512
}
2513

2514
static int testConnectNumOfDefinedDomains(virConnectPtr conn) {
2515
    testConnPtr privconn = conn->privateData;
2516
    int count;
2517

2518
    testDriverLock(privconn);
2519
    count = virDomainObjListNumOfDomains(privconn->domains, false, NULL, NULL);
2520
    testDriverUnlock(privconn);
2521

2522
    return count;
2523 2524
}

2525 2526 2527
static int testConnectListDefinedDomains(virConnectPtr conn,
                                         char **const names,
                                         int maxnames) {
2528

2529
    testConnPtr privconn = conn->privateData;
2530
    int n;
2531

2532
    testDriverLock(privconn);
2533
    memset(names, 0, sizeof(*names)*maxnames);
2534 2535
    n = virDomainObjListGetInactiveNames(privconn->domains, names, maxnames,
                                         NULL, NULL);
2536
    testDriverUnlock(privconn);
2537

2538
    return n;
2539 2540
}

2541
static virDomainPtr testDomainDefineXML(virConnectPtr conn,
2542
                                        const char *xml) {
2543
    testConnPtr privconn = conn->privateData;
2544
    virDomainPtr ret = NULL;
2545
    virDomainDefPtr def;
2546
    virDomainObjPtr dom = NULL;
2547
    virDomainEventPtr event = NULL;
2548
    virDomainDefPtr oldDef = NULL;
2549

2550
    testDriverLock(privconn);
2551 2552
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
                                       1 << VIR_DOMAIN_VIRT_TEST,
2553
                                       VIR_DOMAIN_XML_INACTIVE)) == NULL)
2554
        goto cleanup;
2555

2556
    if (testDomainGenerateIfnames(def) < 0)
2557
        goto cleanup;
2558
    if (!(dom = virDomainObjListAdd(privconn->domains,
2559
                                    def,
2560
                                    privconn->xmlopt,
2561 2562
                                    0,
                                    &oldDef)))
2563
        goto cleanup;
2564
    def = NULL;
2565
    dom->persistent = 1;
2566

2567 2568
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_DEFINED,
2569
                                     !oldDef ?
2570 2571
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
2572

2573
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
2574
    if (ret)
2575
        ret->id = dom->def->id;
2576 2577 2578

cleanup:
    virDomainDefFree(def);
2579
    virDomainDefFree(oldDef);
2580
    if (dom)
2581
        virObjectUnlock(dom);
2582 2583
    if (event)
        testDomainEventQueue(privconn, event);
2584
    testDriverUnlock(privconn);
2585
    return ret;
2586 2587
}

2588 2589 2590
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
                                      int startCell, int maxCells) {
2591
    testConnPtr privconn = conn->privateData;
2592 2593
    int cell;
    size_t i;
2594
    int ret = -1;
2595

2596
    testDriverLock(privconn);
2597
    if (startCell > privconn->numCells) {
2598 2599
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("Range exceeds available cells"));
2600
        goto cleanup;
2601 2602
    }

2603 2604 2605 2606
    for (cell = startCell, i = 0;
         (cell < privconn->numCells && i < maxCells);
         ++cell, ++i) {
        freemems[i] = privconn->cells[cell].mem;
2607
    }
2608
    ret = i;
2609

2610
cleanup:
2611
    testDriverUnlock(privconn);
2612
    return ret;
2613 2614 2615
}


2616
static int testDomainCreateWithFlags(virDomainPtr domain, unsigned int flags) {
2617 2618
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2619
    virDomainEventPtr event = NULL;
2620
    int ret = -1;
2621

2622 2623
    virCheckFlags(0, -1);

2624
    testDriverLock(privconn);
2625 2626
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2627 2628

    if (privdom == NULL) {
2629
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2630
        goto cleanup;
2631
    }
2632

J
Jiri Denemark 已提交
2633
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_SHUTOFF) {
2634 2635
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Domain '%s' is already running"), domain->name);
2636
        goto cleanup;
2637 2638
    }

2639
    if (testDomainStartState(privconn, privdom,
J
Jiri Denemark 已提交
2640
                             VIR_DOMAIN_RUNNING_BOOTED) < 0)
2641 2642 2643
        goto cleanup;
    domain->id = privdom->def->id;

2644 2645 2646
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
2647
    ret = 0;
2648

2649
cleanup:
2650
    if (privdom)
2651
        virObjectUnlock(privdom);
2652 2653
    if (event)
        testDomainEventQueue(privconn, event);
2654
    testDriverUnlock(privconn);
2655
    return ret;
2656 2657
}

2658 2659 2660 2661
static int testDomainCreate(virDomainPtr domain) {
    return testDomainCreateWithFlags(domain, 0);
}

2662 2663 2664
static int testDomainUndefineFlags(virDomainPtr domain,
                                   unsigned int flags)
{
2665 2666
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2667
    virDomainEventPtr event = NULL;
2668
    int ret = -1;
2669

2670 2671
    virCheckFlags(0, -1);

2672
    testDriverLock(privconn);
2673 2674
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2675 2676

    if (privdom == NULL) {
2677
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2678
        goto cleanup;
2679
    }
2680

2681 2682 2683
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
2684 2685
    if (virDomainObjIsActive(privdom)) {
        privdom->persistent = 0;
2686
    } else {
2687 2688
        virDomainObjListRemove(privconn->domains,
                               privdom);
2689 2690 2691
        privdom = NULL;
    }

2692
    ret = 0;
2693

2694
cleanup:
2695
    if (privdom)
2696
        virObjectUnlock(privdom);
2697 2698
    if (event)
        testDomainEventQueue(privconn, event);
2699
    testDriverUnlock(privconn);
2700
    return ret;
2701 2702
}

2703 2704 2705 2706 2707
static int testDomainUndefine(virDomainPtr domain)
{
    return testDomainUndefineFlags(domain, 0);
}

2708 2709 2710
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
2711 2712
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2713
    int ret = -1;
2714

2715
    testDriverLock(privconn);
2716 2717
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2718
    testDriverUnlock(privconn);
2719 2720

    if (privdom == NULL) {
2721
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2722
        goto cleanup;
2723 2724
    }

2725
    *autostart = privdom->autostart;
2726 2727 2728
    ret = 0;

cleanup:
2729
    if (privdom)
2730
        virObjectUnlock(privdom);
2731
    return ret;
2732 2733 2734 2735 2736 2737
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
2738 2739
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2740
    int ret = -1;
2741

2742
    testDriverLock(privconn);
2743 2744
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2745
    testDriverUnlock(privconn);
2746 2747

    if (privdom == NULL) {
2748
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2749
        goto cleanup;
2750 2751
    }

2752
    privdom->autostart = autostart ? 1 : 0;
2753 2754 2755
    ret = 0;

cleanup:
2756
    if (privdom)
2757
        virObjectUnlock(privdom);
2758
    return ret;
2759
}
2760

2761
static char *testDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED,
2762 2763
                                        int *nparams)
{
2764 2765
    char *type = NULL;

2766 2767 2768
    if (nparams)
        *nparams = 1;

2769
    ignore_value(VIR_STRDUP(type, "fair"));
2770

2771 2772 2773
    return type;
}

2774
static int
2775 2776 2777 2778
testDomainGetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int *nparams,
                                      unsigned int flags)
2779
{
2780 2781
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2782
    int ret = -1;
2783

2784 2785
    virCheckFlags(0, -1);

2786
    testDriverLock(privconn);
2787 2788
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2789
    testDriverUnlock(privconn);
2790 2791

    if (privdom == NULL) {
2792
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2793
        goto cleanup;
2794 2795
    }

2796 2797
    if (virTypedParameterAssign(params, VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, 50) < 0)
2798
        goto cleanup;
2799 2800
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
2801 2802

    *nparams = 1;
2803 2804 2805
    ret = 0;

cleanup:
2806
    if (privdom)
2807
        virObjectUnlock(privdom);
2808
    return ret;
2809
}
2810

2811
static int
2812 2813 2814
testDomainGetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int *nparams)
2815
{
2816
    return testDomainGetSchedulerParametersFlags(domain, params, nparams, 0);
2817
}
2818

2819
static int
2820 2821 2822 2823
testDomainSetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int nparams,
                                      unsigned int flags)
2824
{
2825 2826
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2827 2828
    int ret = -1;
    size_t i;
2829

2830
    virCheckFlags(0, -1);
2831 2832 2833 2834
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
2835
        return -1;
2836

2837
    testDriverLock(privconn);
2838 2839
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2840
    testDriverUnlock(privconn);
2841 2842

    if (privdom == NULL) {
2843
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2844
        goto cleanup;
2845 2846
    }

2847
    for (i = 0; i < nparams; i++) {
2848 2849 2850
        if (STREQ(params[i].field, VIR_DOMAIN_SCHEDULER_WEIGHT)) {
            /* XXX */
            /*privdom->weight = params[i].value.ui;*/
2851
        }
2852
    }
2853

2854 2855 2856
    ret = 0;

cleanup:
2857
    if (privdom)
2858
        virObjectUnlock(privdom);
2859
    return ret;
2860 2861
}

2862
static int
2863 2864 2865
testDomainSetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int nparams)
2866
{
2867
    return testDomainSetSchedulerParametersFlags(domain, params, nparams, 0);
2868 2869
}

2870 2871 2872 2873 2874 2875 2876 2877
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;
2878
    int ret = -1;
2879 2880

    testDriverLock(privconn);
2881 2882
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2883 2884 2885
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2886
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2887 2888 2889
        goto error;
    }

2890
    if (virDomainDiskIndexByName(privdom->def, path, false) < 0) {
2891 2892
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path: %s"), path);
2893 2894 2895 2896
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
2897
        virReportSystemError(errno,
2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912
                             "%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)
2913
        virObjectUnlock(privdom);
2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924
    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;
2925 2926
    size_t i;
    int found = 0, ret = -1;
2927 2928

    testDriverLock(privconn);
2929 2930
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2931 2932 2933
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2934
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2935 2936 2937
        goto error;
    }

2938
    for (i = 0; i < privdom->def->nnets; i++) {
2939
        if (privdom->def->nets[i]->ifname &&
2940
            STREQ(privdom->def->nets[i]->ifname, path)) {
2941 2942 2943 2944 2945 2946
            found = 1;
            break;
        }
    }

    if (!found) {
2947 2948
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path, '%s' is not a known interface"), path);
2949 2950 2951 2952
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
2953
        virReportSystemError(errno,
2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971
                             "%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)
2972
        virObjectUnlock(privdom);
2973 2974 2975
    return ret;
}

2976
static virDrvOpenStatus testNetworkOpen(virConnectPtr conn,
2977
                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
2978 2979 2980 2981
                                        unsigned int flags)
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

2982 2983 2984 2985 2986 2987 2988
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

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

2989
static int testNetworkClose(virConnectPtr conn) {
2990 2991 2992 2993 2994
    conn->networkPrivateData = NULL;
    return 0;
}


2995 2996
static virNetworkPtr testNetworkLookupByUUID(virConnectPtr conn,
                                             const unsigned char *uuid)
2997
{
2998 2999
    testConnPtr privconn = conn->privateData;
    virNetworkObjPtr net;
3000
    virNetworkPtr ret = NULL;
3001

3002 3003 3004 3005 3006
    testDriverLock(privconn);
    net = virNetworkFindByUUID(&privconn->networks, uuid);
    testDriverUnlock(privconn);

    if (net == NULL) {
3007
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3008
        goto cleanup;
3009 3010
    }

3011 3012 3013
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

cleanup:
3014 3015
    if (net)
        virNetworkObjUnlock(net);
3016
    return ret;
3017
}
3018

3019
static virNetworkPtr testNetworkLookupByName(virConnectPtr conn,
3020
                                             const char *name)
3021
{
3022
    testConnPtr privconn = conn->privateData;
3023 3024
    virNetworkObjPtr net;
    virNetworkPtr ret = NULL;
3025

3026 3027 3028 3029 3030
    testDriverLock(privconn);
    net = virNetworkFindByName(&privconn->networks, name);
    testDriverUnlock(privconn);

    if (net == NULL) {
3031
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3032
        goto cleanup;
3033 3034
    }

3035 3036 3037
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

cleanup:
3038 3039
    if (net)
        virNetworkObjUnlock(net);
3040
    return ret;
3041 3042 3043
}


3044
static int testConnectNumOfNetworks(virConnectPtr conn) {
3045
    testConnPtr privconn = conn->privateData;
3046 3047
    int numActive = 0;
    size_t i;
3048

3049
    testDriverLock(privconn);
3050
    for (i = 0; i < privconn->networks.count; i++) {
3051
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
3052
        if (virNetworkObjIsActive(privconn->networks.objs[i]))
3053
            numActive++;
3054 3055 3056
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
3057

3058
    return numActive;
3059 3060
}

3061
static int testConnectListNetworks(virConnectPtr conn, char **const names, int nnames) {
3062
    testConnPtr privconn = conn->privateData;
3063 3064
    int n = 0;
    size_t i;
3065

3066
    testDriverLock(privconn);
3067
    memset(names, 0, sizeof(*names)*nnames);
3068
    for (i = 0; i < privconn->networks.count && n < nnames; i++) {
3069
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
3070
        if (virNetworkObjIsActive(privconn->networks.objs[i]) &&
3071
            VIR_STRDUP(names[n++], privconn->networks.objs[i]->def->name) < 0) {
3072
            virNetworkObjUnlock(privconn->networks.objs[i]);
3073
            goto error;
3074 3075 3076 3077
        }
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
3078

3079 3080
    return n;

3081
error:
3082
    for (n = 0; n < nnames; n++)
3083
        VIR_FREE(names[n]);
3084
    testDriverUnlock(privconn);
3085
    return -1;
3086 3087
}

3088
static int testConnectNumOfDefinedNetworks(virConnectPtr conn) {
3089
    testConnPtr privconn = conn->privateData;
3090 3091
    int numInactive = 0;
    size_t i;
3092

3093
    testDriverLock(privconn);
3094
    for (i = 0; i < privconn->networks.count; i++) {
3095
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
3096
        if (!virNetworkObjIsActive(privconn->networks.objs[i]))
3097
            numInactive++;
3098 3099 3100
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
3101

3102
    return numInactive;
3103 3104
}

3105
static int testConnectListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
3106
    testConnPtr privconn = conn->privateData;
3107 3108
    int n = 0;
    size_t i;
3109

3110
    testDriverLock(privconn);
3111
    memset(names, 0, sizeof(*names)*nnames);
3112
    for (i = 0; i < privconn->networks.count && n < nnames; i++) {
3113
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
3114
        if (!virNetworkObjIsActive(privconn->networks.objs[i]) &&
3115
            VIR_STRDUP(names[n++], privconn->networks.objs[i]->def->name) < 0) {
3116
            virNetworkObjUnlock(privconn->networks.objs[i]);
3117
            goto error;
3118 3119 3120 3121
        }
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
3122

3123 3124
    return n;

3125
error:
3126
    for (n = 0; n < nnames; n++)
3127
        VIR_FREE(names[n]);
3128
    testDriverUnlock(privconn);
3129
    return -1;
3130 3131
}

3132
static int
3133
testConnectListAllNetworks(virConnectPtr conn,
3134 3135 3136 3137 3138 3139 3140 3141 3142
                           virNetworkPtr **nets,
                           unsigned int flags)
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

    testDriverLock(privconn);
3143
    ret = virNetworkObjListExport(conn, privconn->networks, nets, NULL, flags);
3144 3145 3146 3147
    testDriverUnlock(privconn);

    return ret;
}
3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158

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) {
3159
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179
        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) {
3180
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191
        goto cleanup;
    }
    ret = obj->persistent;

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


3192
static virNetworkPtr testNetworkCreateXML(virConnectPtr conn, const char *xml) {
3193
    testConnPtr privconn = conn->privateData;
3194
    virNetworkDefPtr def;
3195
    virNetworkObjPtr net = NULL;
3196
    virNetworkPtr ret = NULL;
3197

3198
    testDriverLock(privconn);
3199
    if ((def = virNetworkDefParseString(xml)) == NULL)
3200
        goto cleanup;
3201

3202
    if (!(net = virNetworkAssignDef(&privconn->networks, def, false)))
3203 3204
        goto cleanup;
    def = NULL;
3205
    net->active = 1;
3206

3207
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3208

3209 3210
cleanup:
    virNetworkDefFree(def);
3211 3212 3213
    if (net)
        virNetworkObjUnlock(net);
    testDriverUnlock(privconn);
3214
    return ret;
3215 3216
}

3217
static
3218
virNetworkPtr testNetworkDefineXML(virConnectPtr conn, const char *xml)
3219
{
3220
    testConnPtr privconn = conn->privateData;
3221
    virNetworkDefPtr def;
3222
    virNetworkObjPtr net = NULL;
3223
    virNetworkPtr ret = NULL;
3224

3225
    testDriverLock(privconn);
3226
    if ((def = virNetworkDefParseString(xml)) == NULL)
3227
        goto cleanup;
3228

3229
    if (!(net = virNetworkAssignDef(&privconn->networks, def, false)))
3230 3231
        goto cleanup;
    def = NULL;
3232
    net->persistent = 1;
3233

3234
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3235 3236 3237

cleanup:
    virNetworkDefFree(def);
3238 3239 3240
    if (net)
        virNetworkObjUnlock(net);
    testDriverUnlock(privconn);
3241
    return ret;
3242 3243 3244
}

static int testNetworkUndefine(virNetworkPtr network) {
3245 3246
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3247
    int ret = -1;
3248

3249
    testDriverLock(privconn);
3250 3251 3252 3253
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
3254
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3255
        goto cleanup;
3256
    }
3257

D
Daniel P. Berrange 已提交
3258
    if (virNetworkObjIsActive(privnet)) {
3259 3260
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is still running"), network->name);
3261
        goto cleanup;
3262 3263
    }

3264 3265
    virNetworkRemoveInactive(&privconn->networks,
                             privnet);
3266
    privnet = NULL;
3267
    ret = 0;
3268

3269
cleanup:
3270 3271 3272
    if (privnet)
        virNetworkObjUnlock(privnet);
    testDriverUnlock(privconn);
3273
    return ret;
3274 3275
}

3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323
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;
}

3324
static int testNetworkCreate(virNetworkPtr network) {
3325 3326
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3327
    int ret = -1;
3328

3329
    testDriverLock(privconn);
3330 3331
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
3332
    testDriverUnlock(privconn);
3333 3334

    if (privnet == NULL) {
3335
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3336
        goto cleanup;
3337
    }
3338

D
Daniel P. Berrange 已提交
3339
    if (virNetworkObjIsActive(privnet)) {
3340 3341
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is already running"), network->name);
3342
        goto cleanup;
3343 3344
    }

3345
    privnet->active = 1;
3346
    ret = 0;
3347

3348
cleanup:
3349 3350
    if (privnet)
        virNetworkObjUnlock(privnet);
3351
    return ret;
3352 3353 3354
}

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

3359
    testDriverLock(privconn);
3360 3361 3362 3363
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
3364
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3365
        goto cleanup;
3366
    }
3367

3368 3369 3370 3371
    privnet->active = 0;
    if (!privnet->persistent) {
        virNetworkRemoveInactive(&privconn->networks,
                                 privnet);
3372
        privnet = NULL;
3373
    }
3374 3375 3376
    ret = 0;

cleanup:
3377 3378 3379
    if (privnet)
        virNetworkObjUnlock(privnet);
    testDriverUnlock(privconn);
3380
    return ret;
3381 3382
}

3383
static char *testNetworkGetXMLDesc(virNetworkPtr network,
E
Eric Blake 已提交
3384
                                   unsigned int flags)
3385
{
3386 3387
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3388
    char *ret = NULL;
3389

E
Eric Blake 已提交
3390 3391
    virCheckFlags(0, NULL);

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

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

3402
    ret = virNetworkDefFormat(privnet->def, flags);
3403 3404

cleanup:
3405 3406
    if (privnet)
        virNetworkObjUnlock(privnet);
3407
    return ret;
3408 3409 3410
}

static char *testNetworkGetBridgeName(virNetworkPtr network) {
3411
    testConnPtr privconn = network->conn->privateData;
3412
    char *bridge = NULL;
3413 3414
    virNetworkObjPtr privnet;

3415
    testDriverLock(privconn);
3416 3417
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
3418
    testDriverUnlock(privconn);
3419 3420

    if (privnet == NULL) {
3421
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3422
        goto cleanup;
3423 3424
    }

3425
    if (!(privnet->def->bridge)) {
3426 3427 3428
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("network '%s' does not have a bridge name."),
                       privnet->def->name);
3429 3430 3431
        goto cleanup;
    }

3432
    ignore_value(VIR_STRDUP(bridge, privnet->def->bridge));
3433 3434

cleanup:
3435 3436
    if (privnet)
        virNetworkObjUnlock(privnet);
3437 3438 3439 3440 3441
    return bridge;
}

static int testNetworkGetAutostart(virNetworkPtr network,
                                   int *autostart) {
3442 3443
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3444
    int ret = -1;
3445

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

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

3456
    *autostart = privnet->autostart;
3457 3458 3459
    ret = 0;

cleanup:
3460 3461
    if (privnet)
        virNetworkObjUnlock(privnet);
3462
    return ret;
3463 3464 3465 3466
}

static int testNetworkSetAutostart(virNetworkPtr network,
                                   int autostart) {
3467 3468
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3469
    int ret = -1;
3470

3471
    testDriverLock(privconn);
3472 3473
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
3474
    testDriverUnlock(privconn);
3475 3476

    if (privnet == NULL) {
3477
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3478
        goto cleanup;
3479 3480
    }

3481
    privnet->autostart = autostart ? 1 : 0;
3482 3483 3484
    ret = 0;

cleanup:
3485 3486
    if (privnet)
        virNetworkObjUnlock(privnet);
3487
    return ret;
3488
}
3489

C
Cole Robinson 已提交
3490

L
Laine Stump 已提交
3491 3492 3493 3494
/*
 * Physical host interface routines
 */

3495
static virDrvOpenStatus testInterfaceOpen(virConnectPtr conn,
L
Laine Stump 已提交
3496
                                          virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
3497
                                          unsigned int flags)
L
Laine Stump 已提交
3498
{
E
Eric Blake 已提交
3499 3500
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

L
Laine Stump 已提交
3501 3502 3503 3504 3505 3506 3507
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

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

3508
static int testInterfaceClose(virConnectPtr conn)
L
Laine Stump 已提交
3509 3510 3511 3512 3513 3514
{
    conn->interfacePrivateData = NULL;
    return 0;
}


3515
static int testConnectNumOfInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3516 3517
{
    testConnPtr privconn = conn->privateData;
3518 3519
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3520 3521

    testDriverLock(privconn);
3522
    for (i = 0; (i < privconn->ifaces.count); i++) {
L
Laine Stump 已提交
3523
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3524
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
L
Laine Stump 已提交
3525 3526 3527 3528 3529 3530 3531 3532
            count++;
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3533
static int testConnectListInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3534 3535
{
    testConnPtr privconn = conn->privateData;
3536 3537
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3538 3539 3540

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
3541
    for (i = 0; (i < privconn->ifaces.count) && (n < nnames); i++) {
L
Laine Stump 已提交
3542
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3543
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
3544
            if (VIR_STRDUP(names[n++], privconn->ifaces.objs[i]->def->name) < 0) {
L
Laine Stump 已提交
3545
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
3546
                goto error;
L
Laine Stump 已提交
3547 3548 3549 3550 3551 3552 3553 3554
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

3555
error:
3556
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3557 3558 3559 3560 3561
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

3562
static int testConnectNumOfDefinedInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3563 3564
{
    testConnPtr privconn = conn->privateData;
3565 3566
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3567 3568

    testDriverLock(privconn);
3569
    for (i = 0; i < privconn->ifaces.count; i++) {
L
Laine Stump 已提交
3570
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3571
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
L
Laine Stump 已提交
3572 3573 3574 3575 3576 3577 3578 3579
            count++;
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3580
static int testConnectListDefinedInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3581 3582
{
    testConnPtr privconn = conn->privateData;
3583 3584
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3585 3586 3587

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
3588
    for (i = 0; (i < privconn->ifaces.count) && (n < nnames); i++) {
L
Laine Stump 已提交
3589
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3590
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
3591
            if (VIR_STRDUP(names[n++], privconn->ifaces.objs[i]->def->name) < 0) {
L
Laine Stump 已提交
3592
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
3593
                goto error;
L
Laine Stump 已提交
3594 3595 3596 3597 3598 3599 3600 3601
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

3602
error:
3603
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3604 3605 3606 3607 3608
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

3609
static virInterfacePtr testInterfaceLookupByName(virConnectPtr conn,
L
Laine Stump 已提交
3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620
                                                 const char *name)
{
    testConnPtr privconn = conn->privateData;
    virInterfaceObjPtr iface;
    virInterfacePtr ret = NULL;

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

    if (iface == NULL) {
3621
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632
        goto cleanup;
    }

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

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

3633
static virInterfacePtr testInterfaceLookupByMACString(virConnectPtr conn,
L
Laine Stump 已提交
3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645
                                                      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) {
3646
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3647 3648 3649 3650
        goto cleanup;
    }

    if (ifacect > 1) {
3651
        virReportError(VIR_ERR_MULTIPLE_INTERFACES, NULL);
L
Laine Stump 已提交
3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662
        goto cleanup;
    }

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

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

3663 3664 3665 3666 3667 3668 3669 3670 3671 3672
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) {
3673
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
3674 3675 3676 3677 3678 3679 3680 3681 3682 3683
        goto cleanup;
    }
    ret = virInterfaceObjIsActive(obj);

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

3684
static int testInterfaceChangeBegin(virConnectPtr conn,
E
Eric Blake 已提交
3685
                                    unsigned int flags)
3686 3687 3688 3689
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

E
Eric Blake 已提交
3690 3691
    virCheckFlags(0, -1);

3692 3693
    testDriverLock(privconn);
    if (privconn->transaction_running) {
3694
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3695
                       _("there is another transaction running."));
3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711
        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 已提交
3712
                                     unsigned int flags)
3713 3714 3715 3716
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

E
Eric Blake 已提交
3717 3718
    virCheckFlags(0, -1);

3719 3720 3721
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3722
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3723 3724
                       _("no transaction running, "
                         "nothing to be committed."));
3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739
        goto cleanup;
    }

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

    ret = 0;

cleanup:
    testDriverUnlock(privconn);

    return ret;
}

static int testInterfaceChangeRollback(virConnectPtr conn,
E
Eric Blake 已提交
3740
                                       unsigned int flags)
3741 3742 3743 3744
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

E
Eric Blake 已提交
3745 3746
    virCheckFlags(0, -1);

3747 3748 3749
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3750
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3751 3752
                       _("no transaction running, "
                         "nothing to rollback."));
3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769
        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;
}
3770

L
Laine Stump 已提交
3771
static char *testInterfaceGetXMLDesc(virInterfacePtr iface,
E
Eric Blake 已提交
3772
                                     unsigned int flags)
L
Laine Stump 已提交
3773 3774 3775 3776 3777
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr privinterface;
    char *ret = NULL;

E
Eric Blake 已提交
3778 3779
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
3780 3781 3782 3783 3784 3785
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);
    testDriverUnlock(privconn);

    if (privinterface == NULL) {
3786
        virReportError(VIR_ERR_NO_INTERFACE, __FUNCTION__);
L
Laine Stump 已提交
3787 3788 3789
        goto cleanup;
    }

3790
    ret = virInterfaceDefFormat(privinterface->def);
L
Laine Stump 已提交
3791 3792 3793 3794 3795 3796 3797 3798 3799

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


static virInterfacePtr testInterfaceDefineXML(virConnectPtr conn, const char *xmlStr,
E
Eric Blake 已提交
3800
                                              unsigned int flags)
L
Laine Stump 已提交
3801 3802 3803 3804 3805 3806
{
    testConnPtr privconn = conn->privateData;
    virInterfaceDefPtr def;
    virInterfaceObjPtr iface = NULL;
    virInterfacePtr ret = NULL;

E
Eric Blake 已提交
3807 3808
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
3809
    testDriverLock(privconn);
3810
    if ((def = virInterfaceDefParseString(xmlStr)) == NULL)
L
Laine Stump 已提交
3811 3812
        goto cleanup;

3813
    if ((iface = virInterfaceAssignDef(&privconn->ifaces, def)) == NULL)
L
Laine Stump 已提交
3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837
        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) {
3838
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851
        goto cleanup;
    }

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

cleanup:
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceCreate(virInterfacePtr iface,
E
Eric Blake 已提交
3852
                               unsigned int flags)
L
Laine Stump 已提交
3853 3854 3855 3856 3857
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr privinterface;
    int ret = -1;

E
Eric Blake 已提交
3858 3859
    virCheckFlags(0, -1);

L
Laine Stump 已提交
3860 3861 3862 3863 3864
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);

    if (privinterface == NULL) {
3865
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3866 3867 3868 3869
        goto cleanup;
    }

    if (privinterface->active != 0) {
3870
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884
        goto cleanup;
    }

    privinterface->active = 1;
    ret = 0;

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

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

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

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

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

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

    privinterface->active = 0;
    ret = 0;

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



C
Cole Robinson 已提交
3919 3920 3921 3922
/*
 * Storage Driver routines
 */

3923

3924
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool) {
C
Cole Robinson 已提交
3925 3926 3927 3928 3929

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

3930
    return VIR_STRDUP(pool->configFile, "");
C
Cole Robinson 已提交
3931 3932
}

3933 3934
static virDrvOpenStatus testStorageOpen(virConnectPtr conn,
                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
3935 3936 3937 3938
                                        unsigned int flags)
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950
    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;
}

3951

C
Cole Robinson 已提交
3952 3953 3954
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
                            const unsigned char *uuid) {
3955
    testConnPtr privconn = conn->privateData;
3956 3957
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3958

3959
    testDriverLock(privconn);
3960
    pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid);
3961
    testDriverUnlock(privconn);
3962 3963

    if (pool == NULL) {
3964
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
3965
        goto cleanup;
C
Cole Robinson 已提交
3966 3967
    }

3968 3969
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
3970 3971

cleanup:
3972 3973
    if (pool)
        virStoragePoolObjUnlock(pool);
3974
    return ret;
C
Cole Robinson 已提交
3975 3976 3977 3978 3979
}

static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
                            const char *name) {
3980
    testConnPtr privconn = conn->privateData;
3981 3982
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3983

3984
    testDriverLock(privconn);
3985
    pool = virStoragePoolObjFindByName(&privconn->pools, name);
3986
    testDriverUnlock(privconn);
3987 3988

    if (pool == NULL) {
3989
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
3990
        goto cleanup;
C
Cole Robinson 已提交
3991 3992
    }

3993 3994
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
3995 3996

cleanup:
3997 3998
    if (pool)
        virStoragePoolObjUnlock(pool);
3999
    return ret;
C
Cole Robinson 已提交
4000 4001 4002 4003 4004 4005 4006 4007
}

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

static int
4008
testConnectNumOfStoragePools(virConnectPtr conn) {
4009
    testConnPtr privconn = conn->privateData;
4010 4011
    int numActive = 0;
    size_t i;
C
Cole Robinson 已提交
4012

4013
    testDriverLock(privconn);
4014
    for (i = 0; i < privconn->pools.count; i++)
C
Cole Robinson 已提交
4015 4016
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numActive++;
4017
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4018 4019 4020 4021 4022

    return numActive;
}

static int
4023 4024 4025
testConnectListStoragePools(virConnectPtr conn,
                            char **const names,
                            int nnames) {
4026
    testConnPtr privconn = conn->privateData;
4027 4028
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
4029

4030
    testDriverLock(privconn);
C
Cole Robinson 已提交
4031
    memset(names, 0, sizeof(*names)*nnames);
4032
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
4033
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4034
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
4035
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
4036
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
4037
            goto error;
4038 4039 4040 4041
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4042 4043 4044

    return n;

4045
error:
4046
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
4047
        VIR_FREE(names[n]);
4048
    testDriverUnlock(privconn);
4049
    return -1;
C
Cole Robinson 已提交
4050 4051 4052
}

static int
4053
testConnectNumOfDefinedStoragePools(virConnectPtr conn) {
4054
    testConnPtr privconn = conn->privateData;
4055 4056
    int numInactive = 0;
    size_t i;
C
Cole Robinson 已提交
4057

4058
    testDriverLock(privconn);
4059
    for (i = 0; i < privconn->pools.count; i++) {
4060
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4061 4062
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numInactive++;
4063 4064 4065
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4066 4067 4068 4069 4070

    return numInactive;
}

static int
4071 4072 4073
testConnectListDefinedStoragePools(virConnectPtr conn,
                                   char **const names,
                                   int nnames) {
4074
    testConnPtr privconn = conn->privateData;
4075 4076
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
4077

4078
    testDriverLock(privconn);
C
Cole Robinson 已提交
4079
    memset(names, 0, sizeof(*names)*nnames);
4080
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
4081
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4082
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
4083
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
4084
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
4085
            goto error;
4086 4087 4088 4089
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4090 4091 4092

    return n;

4093
error:
4094
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
4095
        VIR_FREE(names[n]);
4096
    testDriverUnlock(privconn);
4097
    return -1;
C
Cole Robinson 已提交
4098 4099
}

4100
static int
4101 4102 4103
testConnectListAllStoragePools(virConnectPtr conn,
                               virStoragePoolPtr **pools,
                               unsigned int flags)
4104 4105 4106 4107 4108 4109 4110
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

    testDriverLock(privconn);
4111 4112
    ret = virStoragePoolObjListExport(conn, privconn->pools, pools,
                                      NULL, flags);
4113 4114 4115 4116
    testDriverUnlock(privconn);

    return ret;
}
C
Cole Robinson 已提交
4117

4118 4119 4120 4121 4122 4123 4124 4125 4126 4127
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) {
4128
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148
        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) {
4149
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161
        goto cleanup;
    }
    ret = obj->configFile ? 1 : 0;

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



C
Cole Robinson 已提交
4162
static int
4163 4164
testStoragePoolCreate(virStoragePoolPtr pool,
                      unsigned int flags)
E
Eric Blake 已提交
4165
{
4166 4167
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4168
    int ret = -1;
4169

E
Eric Blake 已提交
4170 4171
    virCheckFlags(0, -1);

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

    if (privpool == NULL) {
4178
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4179
        goto cleanup;
4180 4181
    }

4182
    if (virStoragePoolObjIsActive(privpool)) {
4183 4184
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4185 4186
        goto cleanup;
    }
C
Cole Robinson 已提交
4187 4188

    privpool->active = 1;
4189
    ret = 0;
C
Cole Robinson 已提交
4190

4191
cleanup:
4192 4193
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4194
    return ret;
C
Cole Robinson 已提交
4195 4196 4197
}

static char *
4198 4199 4200 4201
testConnectFindStoragePoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type,
                                  const char *srcSpec,
                                  unsigned int flags)
C
Cole Robinson 已提交
4202
{
4203 4204 4205 4206
    virStoragePoolSourcePtr source = NULL;
    int pool_type;
    char *ret = NULL;

E
Eric Blake 已提交
4207 4208
    virCheckFlags(0, NULL);

4209 4210
    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
4211 4212
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
4213 4214 4215 4216
        goto cleanup;
    }

    if (srcSpec) {
4217
        source = virStoragePoolDefParseSourceString(srcSpec, pool_type);
4218 4219 4220 4221 4222 4223 4224
        if (!source)
            goto cleanup;
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
4225
        ignore_value(VIR_STRDUP(ret, defaultPoolSourcesLogicalXML));
4226 4227 4228
        break;

    case VIR_STORAGE_POOL_NETFS:
4229
        if (!source || !source->hosts[0].name) {
4230 4231
            virReportError(VIR_ERR_INVALID_ARG,
                           "%s", _("hostname must be specified for netfs sources"));
4232 4233 4234
            goto cleanup;
        }

4235 4236
        ignore_value(virAsprintf(&ret, defaultPoolSourcesNetFSXML,
                                 source->hosts[0].name));
4237 4238 4239
        break;

    default:
4240 4241
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source discovery"), type);
4242 4243 4244 4245 4246
    }

cleanup:
    virStoragePoolSourceFree(source);
    return ret;
C
Cole Robinson 已提交
4247 4248 4249 4250
}


static virStoragePoolPtr
4251 4252 4253
testStoragePoolCreateXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4254
{
4255
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4256
    virStoragePoolDefPtr def;
4257
    virStoragePoolObjPtr pool = NULL;
4258
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4259

E
Eric Blake 已提交
4260 4261
    virCheckFlags(0, NULL);

4262
    testDriverLock(privconn);
4263
    if (!(def = virStoragePoolDefParseString(xml)))
4264
        goto cleanup;
C
Cole Robinson 已提交
4265

4266 4267 4268 4269
    pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid);
    if (!pool)
        pool = virStoragePoolObjFindByName(&privconn->pools, def->name);
    if (pool) {
4270 4271
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("storage pool already exists"));
4272
        goto cleanup;
C
Cole Robinson 已提交
4273 4274
    }

4275
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4276
        goto cleanup;
4277
    def = NULL;
C
Cole Robinson 已提交
4278

4279
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4280
        virStoragePoolObjRemove(&privconn->pools, pool);
4281 4282
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4283 4284 4285
    }
    pool->active = 1;

4286 4287
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4288 4289 4290

cleanup:
    virStoragePoolDefFree(def);
4291 4292 4293
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4294
    return ret;
C
Cole Robinson 已提交
4295 4296 4297
}

static virStoragePoolPtr
4298 4299 4300
testStoragePoolDefineXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4301
{
4302
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4303
    virStoragePoolDefPtr def;
4304
    virStoragePoolObjPtr pool = NULL;
4305
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4306

E
Eric Blake 已提交
4307 4308
    virCheckFlags(0, NULL);

4309
    testDriverLock(privconn);
4310
    if (!(def = virStoragePoolDefParseString(xml)))
4311
        goto cleanup;
C
Cole Robinson 已提交
4312 4313 4314 4315 4316

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

4317
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4318 4319
        goto cleanup;
    def = NULL;
C
Cole Robinson 已提交
4320

4321
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4322
        virStoragePoolObjRemove(&privconn->pools, pool);
4323 4324
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4325 4326
    }

4327 4328
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4329 4330 4331

cleanup:
    virStoragePoolDefFree(def);
4332 4333 4334
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4335
    return ret;
C
Cole Robinson 已提交
4336 4337 4338
}

static int
4339 4340 4341
testStoragePoolUndefine(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4342
    int ret = -1;
4343

4344
    testDriverLock(privconn);
4345 4346 4347 4348
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
4349
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4350
        goto cleanup;
4351 4352
    }

4353
    if (virStoragePoolObjIsActive(privpool)) {
4354 4355
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4356 4357
        goto cleanup;
    }
C
Cole Robinson 已提交
4358 4359

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

4362
cleanup:
4363 4364 4365
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
4366
    return ret;
C
Cole Robinson 已提交
4367 4368 4369
}

static int
4370
testStoragePoolBuild(virStoragePoolPtr pool,
E
Eric Blake 已提交
4371 4372
                     unsigned int flags)
{
4373 4374
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4375
    int ret = -1;
4376

E
Eric Blake 已提交
4377 4378
    virCheckFlags(0, -1);

4379
    testDriverLock(privconn);
4380 4381
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4382
    testDriverUnlock(privconn);
4383 4384

    if (privpool == NULL) {
4385
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4386
        goto cleanup;
4387 4388
    }

4389
    if (virStoragePoolObjIsActive(privpool)) {
4390 4391
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4392 4393
        goto cleanup;
    }
4394
    ret = 0;
C
Cole Robinson 已提交
4395

4396
cleanup:
4397 4398
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4399
    return ret;
C
Cole Robinson 已提交
4400 4401 4402 4403
}


static int
4404 4405 4406
testStoragePoolDestroy(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4407
    int ret = -1;
4408

4409
    testDriverLock(privconn);
4410 4411 4412 4413
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
4414
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4415
        goto cleanup;
4416 4417 4418
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4419 4420
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4421
        goto cleanup;
4422
    }
C
Cole Robinson 已提交
4423 4424 4425

    privpool->active = 0;

4426
    if (privpool->configFile == NULL) {
C
Cole Robinson 已提交
4427
        virStoragePoolObjRemove(&privconn->pools, privpool);
4428 4429
        privpool = NULL;
    }
4430
    ret = 0;
C
Cole Robinson 已提交
4431

4432
cleanup:
4433 4434 4435
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
4436
    return ret;
C
Cole Robinson 已提交
4437 4438 4439 4440
}


static int
4441
testStoragePoolDelete(virStoragePoolPtr pool,
E
Eric Blake 已提交
4442 4443
                      unsigned int flags)
{
4444 4445
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4446
    int ret = -1;
4447

E
Eric Blake 已提交
4448 4449
    virCheckFlags(0, -1);

4450
    testDriverLock(privconn);
4451 4452
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4453
    testDriverUnlock(privconn);
4454 4455

    if (privpool == NULL) {
4456
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4457 4458 4459 4460
        goto cleanup;
    }

    if (virStoragePoolObjIsActive(privpool)) {
4461 4462
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4463
        goto cleanup;
4464 4465
    }

4466
    ret = 0;
C
Cole Robinson 已提交
4467

4468
cleanup:
4469 4470
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4471
    return ret;
C
Cole Robinson 已提交
4472 4473 4474 4475
}


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

E
Eric Blake 已提交
4483 4484
    virCheckFlags(0, -1);

4485
    testDriverLock(privconn);
4486 4487
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4488
    testDriverUnlock(privconn);
4489 4490

    if (privpool == NULL) {
4491
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4492
        goto cleanup;
4493 4494 4495
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4496 4497
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4498
        goto cleanup;
4499
    }
4500
    ret = 0;
C
Cole Robinson 已提交
4501

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


static int
4510
testStoragePoolGetInfo(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4511
                       virStoragePoolInfoPtr info) {
4512 4513
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4514
    int ret = -1;
4515

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

    if (privpool == NULL) {
4522
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4523
        goto cleanup;
4524
    }
C
Cole Robinson 已提交
4525 4526 4527 4528 4529 4530 4531 4532 4533

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

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

static char *
4543
testStoragePoolGetXMLDesc(virStoragePoolPtr pool,
E
Eric Blake 已提交
4544 4545
                          unsigned int flags)
{
4546 4547
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4548
    char *ret = NULL;
4549

E
Eric Blake 已提交
4550 4551
    virCheckFlags(0, NULL);

4552
    testDriverLock(privconn);
4553 4554
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4555
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4556

4557
    if (privpool == NULL) {
4558
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4559
        goto cleanup;
4560 4561
    }

4562
    ret = virStoragePoolDefFormat(privpool->def);
4563 4564

cleanup:
4565 4566
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4567
    return ret;
C
Cole Robinson 已提交
4568 4569 4570
}

static int
4571
testStoragePoolGetAutostart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4572
                            int *autostart) {
4573 4574
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4575
    int ret = -1;
4576

4577
    testDriverLock(privconn);
4578 4579
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4580
    testDriverUnlock(privconn);
4581 4582

    if (privpool == NULL) {
4583
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4584
        goto cleanup;
4585
    }
C
Cole Robinson 已提交
4586 4587 4588 4589 4590 4591

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

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

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

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

    if (privpool == NULL) {
4613
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4614
        goto cleanup;
4615
    }
C
Cole Robinson 已提交
4616 4617

    if (!privpool->configFile) {
4618 4619
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("pool has no config file"));
4620
        goto cleanup;
C
Cole Robinson 已提交
4621 4622 4623 4624
    }

    autostart = (autostart != 0);
    privpool->autostart = autostart;
4625 4626 4627
    ret = 0;

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


static int
4635
testStoragePoolNumOfVolumes(virStoragePoolPtr pool) {
4636 4637
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4638
    int ret = -1;
4639

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

    if (privpool == NULL) {
4646
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4647
        goto cleanup;
4648 4649 4650
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4651 4652
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4653
        goto cleanup;
4654
    }
C
Cole Robinson 已提交
4655

4656 4657 4658
    ret = privpool->volumes.count;

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

static int
4665
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4666 4667
                           char **const names,
                           int maxnames) {
4668 4669
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4670 4671
    size_t i = 0;
    int n = 0;
C
Cole Robinson 已提交
4672

4673
    memset(names, 0, maxnames * sizeof(*names));
4674 4675

    testDriverLock(privconn);
4676 4677
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4678
    testDriverUnlock(privconn);
4679 4680

    if (privpool == NULL) {
4681
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4682
        goto cleanup;
4683 4684 4685 4686
    }


    if (!virStoragePoolObjIsActive(privpool)) {
4687 4688
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4689
        goto cleanup;
4690 4691
    }

4692
    for (i = 0; i < privpool->volumes.count && n < maxnames; i++) {
4693
        if (VIR_STRDUP(names[n++], privpool->volumes.objs[i]->name) < 0)
C
Cole Robinson 已提交
4694 4695 4696
            goto cleanup;
    }

4697
    virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4698 4699 4700
    return n;

 cleanup:
4701
    for (n = 0; n < maxnames; n++)
C
Cole Robinson 已提交
4702 4703
        VIR_FREE(names[i]);

4704
    memset(names, 0, maxnames * sizeof(*names));
4705 4706
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4707 4708 4709
    return -1;
}

4710 4711 4712 4713 4714 4715
static int
testStoragePoolListAllVolumes(virStoragePoolPtr obj,
                              virStorageVolPtr **vols,
                              unsigned int flags) {
    testConnPtr privconn = obj->conn->privateData;
    virStoragePoolObjPtr pool;
4716
    size_t i;
4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745
    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;
    }

4746
    if (VIR_ALLOC_N(tmp_vols, pool->volumes.count + 1) < 0)
4747 4748
         goto cleanup;

4749
    for (i = 0; i < pool->volumes.count; i++) {
4750 4751
        if (!(vol = virGetStorageVol(obj->conn, pool->def->name,
                                     pool->volumes.objs[i]->name,
4752 4753
                                     pool->volumes.objs[i]->key,
                                     NULL, NULL)))
4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767
            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]);
        }
4768
        VIR_FREE(tmp_vols);
4769 4770 4771 4772 4773 4774 4775
    }

    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
C
Cole Robinson 已提交
4776 4777

static virStorageVolPtr
4778 4779
testStorageVolLookupByName(virStoragePoolPtr pool,
                           const char *name ATTRIBUTE_UNUSED) {
4780 4781 4782
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
4783
    virStorageVolPtr ret = NULL;
4784

4785
    testDriverLock(privconn);
4786 4787
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4788
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4789

4790
    if (privpool == NULL) {
4791
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4792
        goto cleanup;
4793 4794 4795 4796
    }


    if (!virStoragePoolObjIsActive(privpool)) {
4797 4798
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4799
        goto cleanup;
4800 4801 4802 4803 4804
    }

    privvol = virStorageVolDefFindByName(privpool, name);

    if (!privvol) {
4805 4806
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"), name);
4807
        goto cleanup;
C
Cole Robinson 已提交
4808 4809
    }

4810
    ret = virGetStorageVol(pool->conn, privpool->def->name,
4811 4812
                           privvol->name, privvol->key,
                           NULL, NULL);
4813 4814

cleanup:
4815 4816
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4817
    return ret;
C
Cole Robinson 已提交
4818 4819 4820 4821
}


static virStorageVolPtr
4822 4823
testStorageVolLookupByKey(virConnectPtr conn,
                          const char *key) {
4824
    testConnPtr privconn = conn->privateData;
4825
    size_t i;
4826
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4827

4828
    testDriverLock(privconn);
4829
    for (i = 0; i < privconn->pools.count; i++) {
4830
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4831
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4832
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4833 4834
                virStorageVolDefFindByKey(privconn->pools.objs[i], key);

4835 4836 4837 4838
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
4839 4840
                                       privvol->key,
                                       NULL, NULL);
4841
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
4842 4843
                break;
            }
C
Cole Robinson 已提交
4844
        }
4845
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4846
    }
4847
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4848

4849
    if (!ret)
4850 4851
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching key '%s'"), key);
4852 4853

    return ret;
C
Cole Robinson 已提交
4854 4855 4856
}

static virStorageVolPtr
4857 4858
testStorageVolLookupByPath(virConnectPtr conn,
                           const char *path) {
4859
    testConnPtr privconn = conn->privateData;
4860
    size_t i;
4861
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4862

4863
    testDriverLock(privconn);
4864
    for (i = 0; i < privconn->pools.count; i++) {
4865
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4866
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4867
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4868 4869
                virStorageVolDefFindByPath(privconn->pools.objs[i], path);

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

4884
    if (!ret)
4885 4886
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching path '%s'"), path);
4887 4888

    return ret;
C
Cole Robinson 已提交
4889 4890 4891
}

static virStorageVolPtr
4892 4893 4894
testStorageVolCreateXML(virStoragePoolPtr pool,
                        const char *xmldesc,
                        unsigned int flags)
E
Eric Blake 已提交
4895
{
4896 4897
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4898 4899
    virStorageVolDefPtr privvol = NULL;
    virStorageVolPtr ret = NULL;
4900

E
Eric Blake 已提交
4901 4902
    virCheckFlags(0, NULL);

4903
    testDriverLock(privconn);
4904 4905
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4906
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4907

4908
    if (privpool == NULL) {
4909
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4910
        goto cleanup;
4911 4912 4913
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4914 4915
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4916
        goto cleanup;
4917
    }
C
Cole Robinson 已提交
4918

4919
    privvol = virStorageVolDefParseString(privpool->def, xmldesc);
4920
    if (privvol == NULL)
4921
        goto cleanup;
4922 4923

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
4924 4925
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
4926
        goto cleanup;
C
Cole Robinson 已提交
4927 4928 4929
    }

    /* Make sure enough space */
4930
    if ((privpool->def->allocation + privvol->allocation) >
C
Cole Robinson 已提交
4931
         privpool->def->capacity) {
4932 4933 4934
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
4935
        goto cleanup;
C
Cole Robinson 已提交
4936 4937 4938
    }

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

4942 4943
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
4944
                    privvol->name) == -1)
4945
        goto cleanup;
C
Cole Robinson 已提交
4946

4947
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0)
4948
        goto cleanup;
C
Cole Robinson 已提交
4949

4950
    privpool->def->allocation += privvol->allocation;
C
Cole Robinson 已提交
4951 4952 4953
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

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

4956
    ret = virGetStorageVol(pool->conn, privpool->def->name,
4957 4958
                           privvol->name, privvol->key,
                           NULL, NULL);
4959
    privvol = NULL;
4960 4961 4962

cleanup:
    virStorageVolDefFree(privvol);
4963 4964
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4965
    return ret;
C
Cole Robinson 已提交
4966 4967
}

4968
static virStorageVolPtr
4969 4970 4971 4972
testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
                            const char *xmldesc,
                            virStorageVolPtr clonevol,
                            unsigned int flags)
E
Eric Blake 已提交
4973
{
4974 4975 4976 4977 4978
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol = NULL, origvol = NULL;
    virStorageVolPtr ret = NULL;

E
Eric Blake 已提交
4979 4980
    virCheckFlags(0, NULL);

4981 4982 4983 4984 4985 4986
    testDriverLock(privconn);
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
    testDriverUnlock(privconn);

    if (privpool == NULL) {
4987
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4988 4989 4990 4991
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4992 4993
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4994 4995 4996
        goto cleanup;
    }

4997
    privvol = virStorageVolDefParseString(privpool->def, xmldesc);
4998 4999 5000 5001
    if (privvol == NULL)
        goto cleanup;

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
5002 5003
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
5004 5005 5006 5007 5008
        goto cleanup;
    }

    origvol = virStorageVolDefFindByName(privpool, clonevol->name);
    if (!origvol) {
5009 5010 5011
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       clonevol->name);
5012 5013 5014 5015 5016 5017
        goto cleanup;
    }

    /* Make sure enough space */
    if ((privpool->def->allocation + privvol->allocation) >
         privpool->def->capacity) {
5018 5019 5020
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
5021 5022 5023 5024 5025 5026
        goto cleanup;
    }
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    if (VIR_REALLOC_N(privpool->volumes.objs,
5027
                      privpool->volumes.count+1) < 0)
5028 5029
        goto cleanup;

5030 5031
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
5032
                    privvol->name) == -1)
5033 5034
        goto cleanup;

5035
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0)
5036 5037 5038 5039 5040 5041 5042 5043 5044
        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,
5045 5046
                           privvol->name, privvol->key,
                           NULL, NULL);
5047 5048 5049 5050 5051 5052 5053 5054 5055
    privvol = NULL;

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

C
Cole Robinson 已提交
5056
static int
5057 5058
testStorageVolDelete(virStorageVolPtr vol,
                     unsigned int flags)
E
Eric Blake 已提交
5059
{
5060 5061 5062
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5063
    size_t i;
5064
    int ret = -1;
C
Cole Robinson 已提交
5065

E
Eric Blake 已提交
5066 5067
    virCheckFlags(0, -1);

5068
    testDriverLock(privconn);
5069 5070
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5071
    testDriverUnlock(privconn);
5072 5073

    if (privpool == NULL) {
5074
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5075
        goto cleanup;
5076 5077 5078 5079 5080 5081
    }


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

    if (privvol == NULL) {
5082 5083 5084
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5085
        goto cleanup;
5086 5087 5088
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5089 5090
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5091
        goto cleanup;
5092 5093 5094
    }


C
Cole Robinson 已提交
5095 5096 5097 5098
    privpool->def->allocation -= privvol->allocation;
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

5099
    for (i = 0; i < privpool->volumes.count; i++) {
C
Cole Robinson 已提交
5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117
        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;
        }
    }
5118
    ret = 0;
C
Cole Robinson 已提交
5119

5120
cleanup:
5121 5122
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5123
    return ret;
C
Cole Robinson 已提交
5124 5125 5126 5127 5128
}


static int testStorageVolumeTypeForPool(int pooltype) {

5129
    switch (pooltype) {
C
Cole Robinson 已提交
5130 5131 5132 5133 5134 5135 5136 5137 5138 5139
        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
5140 5141
testStorageVolGetInfo(virStorageVolPtr vol,
                      virStorageVolInfoPtr info) {
5142 5143 5144
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5145
    int ret = -1;
5146

5147
    testDriverLock(privconn);
5148 5149
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5150
    testDriverUnlock(privconn);
5151 5152

    if (privpool == NULL) {
5153
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5154
        goto cleanup;
5155 5156 5157 5158 5159
    }

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

    if (privvol == NULL) {
5160 5161 5162
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5163
        goto cleanup;
5164 5165 5166
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5167 5168
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5169
        goto cleanup;
5170
    }
C
Cole Robinson 已提交
5171 5172 5173 5174 5175

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

5178
cleanup:
5179 5180
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5181
    return ret;
C
Cole Robinson 已提交
5182 5183 5184
}

static char *
5185 5186
testStorageVolGetXMLDesc(virStorageVolPtr vol,
                         unsigned int flags)
E
Eric Blake 已提交
5187
{
5188 5189 5190
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5191
    char *ret = NULL;
5192

E
Eric Blake 已提交
5193 5194
    virCheckFlags(0, NULL);

5195
    testDriverLock(privconn);
5196 5197
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5198
    testDriverUnlock(privconn);
5199 5200

    if (privpool == NULL) {
5201
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5202
        goto cleanup;
5203 5204 5205 5206 5207
    }

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

    if (privvol == NULL) {
5208 5209 5210
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5211
        goto cleanup;
5212
    }
C
Cole Robinson 已提交
5213

5214
    if (!virStoragePoolObjIsActive(privpool)) {
5215 5216
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5217
        goto cleanup;
5218 5219
    }

5220
    ret = virStorageVolDefFormat(privpool->def, privvol);
5221 5222

cleanup:
5223 5224
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5225
    return ret;
C
Cole Robinson 已提交
5226 5227 5228
}

static char *
5229
testStorageVolGetPath(virStorageVolPtr vol) {
5230 5231 5232
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5233
    char *ret = NULL;
5234

5235
    testDriverLock(privconn);
5236 5237
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5238
    testDriverUnlock(privconn);
5239 5240

    if (privpool == NULL) {
5241
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5242
        goto cleanup;
5243 5244 5245 5246 5247
    }

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

    if (privvol == NULL) {
5248 5249 5250
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5251
        goto cleanup;
5252 5253 5254
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5255 5256
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5257
        goto cleanup;
5258 5259
    }

5260
    ignore_value(VIR_STRDUP(ret, privvol->target.path));
5261 5262

cleanup:
5263 5264
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
5265 5266 5267
    return ret;
}

5268

5269
/* Node device implementations */
5270 5271 5272
static virDrvOpenStatus testNodeDeviceOpen(virConnectPtr conn,
                                           virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                           unsigned int flags)
E
Eric Blake 已提交
5273 5274 5275
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

5276 5277 5278
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

5279
    conn->nodeDevicePrivateData = conn->privateData;
5280 5281 5282
    return VIR_DRV_OPEN_SUCCESS;
}

5283 5284
static int testNodeDeviceClose(virConnectPtr conn) {
    conn->nodeDevicePrivateData = NULL;
5285 5286 5287
    return 0;
}

5288 5289 5290
static int
testNodeNumOfDevices(virConnectPtr conn,
                     const char *cap,
E
Eric Blake 已提交
5291
                     unsigned int flags)
5292 5293 5294
{
    testConnPtr driver = conn->privateData;
    int ndevs = 0;
5295
    size_t i;
5296

E
Eric Blake 已提交
5297 5298
    virCheckFlags(0, -1);

5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313
    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 已提交
5314
                    unsigned int flags)
5315 5316 5317
{
    testConnPtr driver = conn->privateData;
    int ndevs = 0;
5318
    size_t i;
5319

E
Eric Blake 已提交
5320 5321
    virCheckFlags(0, -1);

5322 5323 5324 5325 5326
    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)) {
5327
            if (VIR_STRDUP(names[ndevs++], driver->devs.objs[i]->def->name) < 0) {
5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357
                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) {
5358
        virReportError(VIR_ERR_NO_NODE_DEVICE, NULL);
5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370
        goto cleanup;
    }

    ret = virGetNodeDevice(conn, name);

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

static char *
5371
testNodeDeviceGetXMLDesc(virNodeDevicePtr dev,
E
Eric Blake 已提交
5372
                         unsigned int flags)
5373 5374 5375 5376 5377
{
    testConnPtr driver = dev->conn->privateData;
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

E
Eric Blake 已提交
5378 5379
    virCheckFlags(0, NULL);

5380 5381 5382 5383 5384
    testDriverLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
    testDriverUnlock(driver);

    if (!obj) {
5385 5386 5387
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5388 5389 5390
        goto cleanup;
    }

5391
    ret = virNodeDeviceDefFormat(obj->def);
5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410

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) {
5411 5412 5413
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5414 5415 5416 5417
        goto cleanup;
    }

    if (obj->def->parent) {
5418
        ignore_value(VIR_STRDUP(ret, obj->def->parent));
5419
    } else {
5420 5421
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no parent for this device"));
5422 5423 5424 5425 5426 5427 5428 5429
    }

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

5430

5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444
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) {
5445 5446 5447
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475
        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) {
5476 5477 5478
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5479 5480 5481 5482
        goto cleanup;
    }

    for (caps = obj->def->caps; caps && ncaps < maxnames; caps = caps->next) {
5483
        if (VIR_STRDUP(names[ncaps++], virNodeDevCapTypeToString(caps->type)) < 0)
5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498
            goto cleanup;
    }
    ret = ncaps;

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

5499 5500 5501
static virNodeDevicePtr
testNodeDeviceCreateXML(virConnectPtr conn,
                        const char *xmlDesc,
E
Eric Blake 已提交
5502
                        unsigned int flags)
5503 5504 5505 5506 5507 5508 5509 5510 5511
{
    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 已提交
5512 5513
    virCheckFlags(0, NULL);

5514 5515
    testDriverLock(driver);

5516
    def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, NULL);
5517 5518 5519 5520 5521
    if (def == NULL) {
        goto cleanup;
    }

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

5526
    if (virNodeDeviceGetParentHost(&driver->devs,
5527 5528 5529 5530 5531 5532 5533 5534 5535
                                   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);
5536
    if (VIR_STRDUP(def->name, wwpn) < 0)
5537 5538 5539 5540 5541 5542 5543 5544 5545
        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;

5546
        caps->data.scsi_host.host = virRandomBits(10);
5547 5548 5549 5550
        caps = caps->next;
    }


5551
    if (!(obj = virNodeDeviceAssignDef(&driver->devs, def))) {
5552 5553 5554 5555 5556 5557 5558 5559
        goto cleanup;
    }
    virNodeDeviceObjUnlock(obj);

    dev = virGetNodeDevice(conn, def->name);
    def = NULL;
cleanup:
    testDriverUnlock(driver);
5560
    virNodeDeviceDefFree(def);
5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579
    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) {
5580
        virReportError(VIR_ERR_NO_NODE_DEVICE, NULL);
5581 5582 5583
        goto out;
    }

5584
    if (virNodeDeviceGetWWNs(obj->def, &wwnn, &wwpn) == -1) {
5585 5586 5587
        goto out;
    }

5588
    if (VIR_STRDUP(parent_name, obj->def->parent) < 0)
5589 5590 5591 5592 5593 5594 5595 5596 5597
        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 */
5598
    if (virNodeDeviceGetParentHost(&driver->devs,
5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617
                                   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;
}

5618 5619

/* Domain event implementations */
5620
static int
5621 5622 5623 5624
testConnectDomainEventRegister(virConnectPtr conn,
                               virConnectDomainEventCallback callback,
                               void *opaque,
                               virFreeCallback freecb)
5625 5626 5627 5628 5629
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
5630 5631 5632
    ret = virDomainEventStateRegister(conn,
                                      driver->domainEventState,
                                      callback, opaque, freecb);
5633 5634 5635 5636 5637
    testDriverUnlock(driver);

    return ret;
}

5638

5639
static int
5640 5641
testConnectDomainEventDeregister(virConnectPtr conn,
                                 virConnectDomainEventCallback callback)
5642 5643 5644 5645 5646
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
5647 5648 5649
    ret = virDomainEventStateDeregister(conn,
                                        driver->domainEventState,
                                        callback);
5650 5651 5652 5653 5654
    testDriverUnlock(driver);

    return ret;
}

5655 5656

static int
5657 5658 5659 5660 5661 5662
testConnectDomainEventRegisterAny(virConnectPtr conn,
                                  virDomainPtr dom,
                                  int eventID,
                                  virConnectDomainEventGenericCallback callback,
                                  void *opaque,
                                  virFreeCallback freecb)
5663 5664 5665 5666 5667
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
5668 5669 5670 5671
    if (virDomainEventStateRegisterID(conn,
                                      driver->domainEventState,
                                      dom, eventID,
                                      callback, opaque, freecb, &ret) < 0)
5672
        ret = -1;
5673 5674 5675 5676 5677 5678
    testDriverUnlock(driver);

    return ret;
}

static int
5679 5680
testConnectDomainEventDeregisterAny(virConnectPtr conn,
                                    int callbackID)
5681 5682 5683 5684 5685
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
5686 5687 5688
    ret = virDomainEventStateDeregisterID(conn,
                                          driver->domainEventState,
                                          callbackID);
5689 5690 5691 5692 5693 5694
    testDriverUnlock(driver);

    return ret;
}


5695 5696 5697 5698
/* driver must be locked before calling */
static void testDomainEventQueue(testConnPtr driver,
                                 virDomainEventPtr event)
{
5699
    virDomainEventStateQueue(driver->domainEventState, event);
5700 5701
}

5702 5703
static virDrvOpenStatus testSecretOpen(virConnectPtr conn,
                                       virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
5704 5705 5706 5707
                                       unsigned int flags)
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

5708 5709 5710
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

5711
    conn->secretPrivateData = conn->privateData;
5712 5713 5714 5715 5716 5717 5718
    return VIR_DRV_OPEN_SUCCESS;
}

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

5720 5721 5722

static virDrvOpenStatus testNWFilterOpen(virConnectPtr conn,
                                         virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
5723 5724 5725 5726
                                         unsigned int flags)
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

5727 5728 5729
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

5730
    conn->nwfilterPrivateData = conn->privateData;
5731 5732 5733 5734 5735 5736 5737 5738
    return VIR_DRV_OPEN_SUCCESS;
}

static int testNWFilterClose(virConnectPtr conn) {
    conn->nwfilterPrivateData = NULL;
    return 0;
}

5739

5740 5741 5742
static int testConnectListAllDomains(virConnectPtr conn,
                                     virDomainPtr **domains,
                                     unsigned int flags)
5743 5744 5745 5746
{
    testConnPtr privconn = conn->privateData;
    int ret;

O
Osier Yang 已提交
5747
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
5748 5749

    testDriverLock(privconn);
5750 5751
    ret = virDomainObjListExport(privconn->domains, conn, domains,
                                 NULL, flags);
5752 5753 5754 5755 5756
    testDriverUnlock(privconn);

    return ret;
}

5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769
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) {
5770
        if (VIR_ALLOC_N(*cpumap, 1) < 0)
5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784
            goto cleanup;
        *cpumap[0] = 0x15;
    }

    if (online)
        *online = 3;

    ret = 8;

cleanup:
    testDriverUnlock(privconn);
    return ret;
}

5785 5786 5787 5788 5789 5790 5791 5792 5793 5794
static char *
testDomainScreenshot(virDomainPtr dom ATTRIBUTE_UNUSED,
                     virStreamPtr st,
                     unsigned int screen ATTRIBUTE_UNUSED,
                     unsigned int flags)
{
    char *ret = NULL;

    virCheckFlags(0, NULL);

5795
    if (VIR_STRDUP(ret, "image/png") < 0)
5796 5797 5798 5799 5800 5801 5802 5803
        return NULL;

    if (virFDStreamOpenFile(st, PKGDATADIR "/libvirtLogo.png", 0, 0, O_RDONLY < 0))
        VIR_FREE(ret);

    return ret;
}

5804

5805
static virDriver testDriver = {
5806 5807
    .no = VIR_DRV_TEST,
    .name = "Test",
5808 5809 5810
    .connectOpen = testConnectOpen, /* 0.1.1 */
    .connectClose = testConnectClose, /* 0.1.1 */
    .connectGetVersion = testConnectGetVersion, /* 0.1.1 */
5811
    .connectGetHostname = testConnectGetHostname, /* 0.6.3 */
5812
    .connectGetMaxVcpus = testConnectGetMaxVcpus, /* 0.3.2 */
5813
    .nodeGetInfo = testNodeGetInfo, /* 0.1.1 */
5814 5815 5816 5817
    .connectGetCapabilities = testConnectGetCapabilities, /* 0.2.1 */
    .connectListDomains = testConnectListDomains, /* 0.1.1 */
    .connectNumOfDomains = testConnectNumOfDomains, /* 0.1.1 */
    .connectListAllDomains = testConnectListAllDomains, /* 0.9.13 */
5818
    .domainCreateXML = testDomainCreateXML, /* 0.1.4 */
5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832
    .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 */
5833 5834
    .domainGetState = testDomainGetState, /* 0.9.2 */
    .domainSave = testDomainSave, /* 0.3.2 */
5835
    .domainSaveFlags = testDomainSaveFlags, /* 0.9.4 */
5836
    .domainRestore = testDomainRestore, /* 0.3.2 */
5837
    .domainRestoreFlags = testDomainRestoreFlags, /* 0.9.4 */
5838
    .domainCoreDump = testDomainCoreDump, /* 0.3.2 */
5839
    .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */
5840 5841 5842 5843 5844 5845
    .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 */
5846 5847
    .connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
    .connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
5848 5849 5850 5851
    .domainCreate = testDomainCreate, /* 0.1.11 */
    .domainCreateWithFlags = testDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = testDomainDefineXML, /* 0.1.11 */
    .domainUndefine = testDomainUndefine, /* 0.1.11 */
5852
    .domainUndefineFlags = testDomainUndefineFlags, /* 0.9.4 */
5853 5854 5855
    .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
    .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
    .domainGetSchedulerType = testDomainGetSchedulerType, /* 0.3.2 */
5856 5857 5858 5859
    .domainGetSchedulerParameters = testDomainGetSchedulerParameters, /* 0.3.2 */
    .domainGetSchedulerParametersFlags = testDomainGetSchedulerParametersFlags, /* 0.9.2 */
    .domainSetSchedulerParameters = testDomainSetSchedulerParameters, /* 0.3.2 */
    .domainSetSchedulerParametersFlags = testDomainSetSchedulerParametersFlags, /* 0.9.2 */
5860 5861 5862
    .domainBlockStats = testDomainBlockStats, /* 0.7.0 */
    .domainInterfaceStats = testDomainInterfaceStats, /* 0.7.0 */
    .nodeGetCellsFreeMemory = testNodeGetCellsFreeMemory, /* 0.4.2 */
5863 5864 5865 5866
    .connectDomainEventRegister = testConnectDomainEventRegister, /* 0.6.0 */
    .connectDomainEventDeregister = testConnectDomainEventDeregister, /* 0.6.0 */
    .connectIsEncrypted = testConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = testConnectIsSecure, /* 0.7.3 */
5867 5868 5869
    .domainIsActive = testDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = testDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = testDomainIsUpdated, /* 0.8.6 */
5870 5871 5872
    .connectDomainEventRegisterAny = testConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = testConnectDomainEventDeregisterAny, /* 0.8.0 */
    .connectIsAlive = testConnectIsAlive, /* 0.9.8 */
5873
    .nodeGetCPUMap = testNodeGetCPUMap, /* 1.0.0 */
5874
    .domainScreenshot = testDomainScreenshot, /* 1.0.5 */
5875 5876 5877 5878
};

static virNetworkDriver testNetworkDriver = {
    "Test",
5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889
    .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 */
5890
    .networkUndefine = testNetworkUndefine, /* 0.3.2 */
5891
    .networkUpdate = testNetworkUpdate, /* 0.10.2 */
5892
    .networkCreate = testNetworkCreate, /* 0.3.2 */
5893 5894 5895 5896 5897 5898 5899
    .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 */
5900 5901
};

L
Laine Stump 已提交
5902 5903
static virInterfaceDriver testInterfaceDriver = {
    "Test",                     /* name */
5904 5905 5906 5907 5908 5909 5910 5911
    .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 */
5912 5913 5914 5915 5916 5917
    .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 */
5918 5919 5920
    .interfaceChangeBegin = testInterfaceChangeBegin,   /* 0.9.2 */
    .interfaceChangeCommit = testInterfaceChangeCommit,  /* 0.9.2 */
    .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */
L
Laine Stump 已提交
5921 5922 5923
};


5924 5925
static virStorageDriver testStorageDriver = {
    .name = "Test",
5926 5927
    .storageOpen = testStorageOpen, /* 0.4.1 */
    .storageClose = testStorageClose, /* 0.4.1 */
5928

5929 5930 5931 5932 5933 5934
    .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 */
5935 5936 5937
    .storagePoolLookupByName = testStoragePoolLookupByName, /* 0.5.0 */
    .storagePoolLookupByUUID = testStoragePoolLookupByUUID, /* 0.5.0 */
    .storagePoolLookupByVolume = testStoragePoolLookupByVolume, /* 0.5.0 */
5938 5939
    .storagePoolCreateXML = testStoragePoolCreateXML, /* 0.5.0 */
    .storagePoolDefineXML = testStoragePoolDefineXML, /* 0.5.0 */
5940 5941
    .storagePoolBuild = testStoragePoolBuild, /* 0.5.0 */
    .storagePoolUndefine = testStoragePoolUndefine, /* 0.5.0 */
5942
    .storagePoolCreate = testStoragePoolCreate, /* 0.5.0 */
5943 5944 5945 5946 5947 5948 5949
    .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 */
5950
    .storagePoolNumOfVolumes = testStoragePoolNumOfVolumes, /* 0.5.0 */
5951 5952 5953
    .storagePoolListVolumes = testStoragePoolListVolumes, /* 0.5.0 */
    .storagePoolListAllVolumes = testStoragePoolListAllVolumes, /* 0.10.2 */

5954 5955 5956 5957 5958 5959 5960 5961 5962
    .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 */
5963 5964
    .storagePoolIsActive = testStoragePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = testStoragePoolIsPersistent, /* 0.7.3 */
5965 5966
};

5967
static virNodeDeviceDriver testNodeDeviceDriver = {
5968
    .name = "Test",
5969 5970
    .nodeDeviceOpen = testNodeDeviceOpen, /* 0.6.0 */
    .nodeDeviceClose = testNodeDeviceClose, /* 0.6.0 */
5971 5972 5973 5974 5975 5976 5977 5978 5979 5980

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

5983 5984
static virSecretDriver testSecretDriver = {
    .name = "Test",
5985 5986
    .secretOpen = testSecretOpen, /* 0.7.1 */
    .secretClose = testSecretClose, /* 0.7.1 */
5987
};
5988 5989


5990 5991
static virNWFilterDriver testNWFilterDriver = {
    .name = "Test",
5992 5993
    .nwfilterOpen = testNWFilterOpen, /* 0.8.0 */
    .nwfilterClose = testNWFilterClose, /* 0.8.0 */
5994 5995
};

5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
    if (virRegisterDriver(&testDriver) < 0)
        return -1;
    if (virRegisterNetworkDriver(&testNetworkDriver) < 0)
        return -1;
L
Laine Stump 已提交
6008 6009
    if (virRegisterInterfaceDriver(&testInterfaceDriver) < 0)
        return -1;
6010 6011
    if (virRegisterStorageDriver(&testStorageDriver) < 0)
        return -1;
6012
    if (virRegisterNodeDeviceDriver(&testNodeDeviceDriver) < 0)
6013
        return -1;
6014 6015
    if (virRegisterSecretDriver(&testSecretDriver) < 0)
        return -1;
6016 6017
    if (virRegisterNWFilterDriver(&testNWFilterDriver) < 0)
        return -1;
6018

6019 6020
    return 0;
}