test_driver.c 205.2 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
#include <libxml/xpathInternals.h>
34

35

36
#include "virerror.h"
37
#include "datatypes.h"
38
#include "test_driver.h"
39
#include "virbuffer.h"
40
#include "viruuid.h"
41
#include "capabilities.h"
42
#include "configmake.h"
43
#include "viralloc.h"
44
#include "network_conf.h"
L
Laine Stump 已提交
45
#include "interface_conf.h"
46
#include "domain_conf.h"
47
#include "domain_event.h"
48
#include "snapshot_conf.h"
49
#include "fdstream.h"
C
Cole Robinson 已提交
50
#include "storage_conf.h"
51
#include "node_device_conf.h"
52
#include "virxml.h"
53
#include "virthread.h"
54
#include "virlog.h"
E
Eric Blake 已提交
55
#include "virfile.h"
56
#include "virtypedparam.h"
57
#include "virrandom.h"
58
#include "virstring.h"
59
#include "cpu/cpu.h"
60

61 62
#define VIR_FROM_THIS VIR_FROM_TEST

63 64 65 66 67 68 69 70 71
/* Driver specific info to carry with a domain */
struct _testDomainObjPrivate {
    virVcpuInfoPtr vcpu_infos;

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

72 73 74 75 76
#define MAX_CPUS 128

struct _testCell {
    unsigned long mem;
    int numCpus;
77
    virCapsHostNUMACellCPU cpus[MAX_CPUS];
78 79 80 81 82
};
typedef struct _testCell testCell;
typedef struct _testCell *testCellPtr;

#define MAX_CELLS 128
83

84
struct _testConn {
85
    virMutex lock;
86

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

102
    virDomainEventStatePtr domainEventState;
103 104 105
};
typedef struct _testConn testConn;
typedef struct _testConn *testConnPtr;
106

107
#define TEST_MODEL "i686"
108
#define TEST_MODEL_WORDSIZE 32
109
#define TEST_EMULATOR "/usr/bin/test-hv"
110

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

122

123
static int testConnectClose(virConnectPtr conn);
124 125 126 127
static void testDomainEventQueue(testConnPtr driver,
                                 virDomainEventPtr event);


128 129
static void testDriverLock(testConnPtr driver)
{
130
    virMutexLock(&driver->lock);
131 132 133 134
}

static void testDriverUnlock(testConnPtr driver)
{
135
    virMutexUnlock(&driver->lock);
136 137
}

138 139 140 141 142 143 144 145 146 147 148 149 150 151
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 已提交
152
    VIR_FREE(priv->vcpu_infos);
153 154 155 156
    VIR_FREE(priv->cpumaps);
    VIR_FREE(priv);
}

157 158 159 160 161 162
#define TEST_NAMESPACE_HREF "http://libvirt.org/schemas/domain/test/1.0"

typedef struct _testDomainNamespaceDef testDomainNamespaceDef;
typedef testDomainNamespaceDef *testDomainNamespaceDefPtr;
struct _testDomainNamespaceDef {
    int runstate;
163
    bool transient;
C
Cole Robinson 已提交
164
    bool hasManagedSave;
165 166 167

    unsigned int num_snap_nodes;
    xmlNodePtr *snap_nodes;
168 169 170 171 172 173
};

static void
testDomainDefNamespaceFree(void *data)
{
    testDomainNamespaceDefPtr nsdata = data;
174 175 176 177 178 179 180 181 182
    size_t i;

    if (!nsdata)
        return;

    for (i = 0; i < nsdata->num_snap_nodes; i++)
        xmlFreeNode(nsdata->snap_nodes[i]);

    VIR_FREE(nsdata->snap_nodes);
183 184 185 186 187 188 189 190 191 192
    VIR_FREE(nsdata);
}

static int
testDomainDefNamespaceParse(xmlDocPtr xml ATTRIBUTE_UNUSED,
                            xmlNodePtr root ATTRIBUTE_UNUSED,
                            xmlXPathContextPtr ctxt,
                            void **data)
{
    testDomainNamespaceDefPtr nsdata = NULL;
193 194 195
    xmlNodePtr *nodes = NULL;
    int tmp, n;
    size_t i;
196 197 198 199 200 201 202 203 204 205 206 207 208
    unsigned int tmpuint;

    if (xmlXPathRegisterNs(ctxt, BAD_CAST "test",
                           BAD_CAST TEST_NAMESPACE_HREF) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to register xml namespace '%s'"),
                       TEST_NAMESPACE_HREF);
        return -1;
    }

    if (VIR_ALLOC(nsdata) < 0)
        return -1;

209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
    n = virXPathNodeSet("./test:domainsnapshot", ctxt, &nodes);
    if (n < 0)
        goto error;

    if (n && VIR_ALLOC_N(nsdata->snap_nodes, n) < 0)
        goto error;

    for (i = 0; i < n; i++) {
        xmlNodePtr newnode = xmlCopyNode(nodes[i], 1);
        if (!newnode) {
            virReportOOMError();
            goto error;
        }

        nsdata->snap_nodes[nsdata->num_snap_nodes] = newnode;
        nsdata->num_snap_nodes++;
    }
    VIR_FREE(nodes);

228 229 230 231 232 233 234
    tmp = virXPathBoolean("boolean(./test:transient)", ctxt);
    if (tmp == -1) {
        virReportError(VIR_ERR_XML_ERROR, "%s", _("invalid transient"));
        goto error;
    }
    nsdata->transient = tmp;

C
Cole Robinson 已提交
235 236 237 238 239 240 241
    tmp = virXPathBoolean("boolean(./test:hasmanagedsave)", ctxt);
    if (tmp == -1) {
        virReportError(VIR_ERR_XML_ERROR, "%s", _("invalid hasmanagedsave"));
        goto error;
    }
    nsdata->hasManagedSave = tmp;

242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
    tmp = virXPathUInt("string(./test:runstate)", ctxt, &tmpuint);
    if (tmp == 0) {
        if (tmpuint >= VIR_DOMAIN_LAST) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("runstate '%d' out of range'"), tmpuint);
            goto error;
        }
        nsdata->runstate = tmpuint;
    } else if (tmp == -1) {
        nsdata->runstate = VIR_DOMAIN_RUNNING;
    } else if (tmp == -2) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid runstate"));
        goto error;
    }

258 259 260 261 262
    if (nsdata->transient && nsdata->runstate == VIR_DOMAIN_SHUTOFF) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
            _("transient domain cannot have runstate 'shutoff'"));
        goto error;
    }
C
Cole Robinson 已提交
263 264 265 266 267
    if (nsdata->hasManagedSave && nsdata->runstate != VIR_DOMAIN_SHUTOFF) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
            _("domain with managedsave data can only have runstate 'shutoff'"));
        goto error;
    }
268

269 270 271 272
    *data = nsdata;
    return 0;

error:
273
    VIR_FREE(nodes);
274 275 276
    testDomainDefNamespaceFree(nsdata);
    return -1;
}
277

278
static virDomainXMLOptionPtr
279 280
testBuildXMLConfig(void)
{
281 282 283 284 285 286 287 288 289 290 291 292
    virDomainXMLPrivateDataCallbacks priv = {
        .alloc = testDomainObjPrivateAlloc,
        .free = testDomainObjPrivateFree
    };

    /* All our XML extensions are input only, so we only need to parse */
    virDomainXMLNamespace ns = {
        .parse = testDomainDefNamespaceParse,
        .free = testDomainDefNamespaceFree,
    };

    return virDomainXMLOptionNew(NULL, &priv, &ns);
293 294 295
}


296 297
static virCapsPtr
testBuildCapabilities(virConnectPtr conn) {
298
    testConnPtr privconn = conn->privateData;
299 300 301
    virCapsPtr caps;
    virCapsGuestPtr guest;
    const char *const guest_types[] = { "hvm", "xen" };
302
    size_t i;
303

304
    if ((caps = virCapabilitiesNew(VIR_ARCH_I686, 0, 0)) == NULL)
305
        goto error;
306

307
    if (virCapabilitiesAddHostFeature(caps, "pae") < 0)
308
        goto error;
309
    if (virCapabilitiesAddHostFeature(caps ,"nonpae") < 0)
310
        goto error;
311

312
    for (i = 0; i < privconn->numCells; i++) {
313 314 315
        virCapsHostNUMACellCPUPtr cpu_cells;

        if (VIR_ALLOC_N(cpu_cells, privconn->cells[i].numCpus) < 0)
316
            goto error;
317 318 319 320 321

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


322
        if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].numCpus,
323
                                           0, cpu_cells) < 0)
324
            goto error;
325 326
    }

327
    for (i = 0; i < ARRAY_CARDINALITY(guest_types); i++) {
328 329
        if ((guest = virCapabilitiesAddGuest(caps,
                                             guest_types[i],
330
                                             VIR_ARCH_I686,
331 332 333 334
                                             TEST_EMULATOR,
                                             NULL,
                                             0,
                                             NULL)) == NULL)
335
            goto error;
336

337 338 339 340 341 342
        if (virCapabilitiesAddGuestDomain(guest,
                                          "test",
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
343
            goto error;
344

345
        if (virCapabilitiesAddGuestFeature(guest, "pae", 1, 1) == NULL)
346
            goto error;
347
        if (virCapabilitiesAddGuestFeature(guest ,"nonpae", 1, 1) == NULL)
348
            goto error;
349 350
    }

351 352
    caps->host.nsecModels = 1;
    if (VIR_ALLOC_N(caps->host.secModels, caps->host.nsecModels) < 0)
353
        goto error;
354 355
    if (VIR_STRDUP(caps->host.secModels[0].model, "testSecurity") < 0)
        goto error;
356

357 358
    if (VIR_STRDUP(caps->host.secModels[0].doi, "") < 0)
        goto error;
359

360
    return caps;
361

362
error:
363
    virObjectUnref(caps);
364
    return NULL;
365 366
}

367

368 369 370
static const char *defaultDomainXML =
"<domain type='test'>"
"  <name>test</name>"
371
"  <uuid>6695eb01-f6a4-8304-79aa-97f2502e193f</uuid>"
372 373 374 375 376 377 378
"  <memory>8388608</memory>"
"  <currentMemory>2097152</currentMemory>"
"  <vcpu>2</vcpu>"
"  <os>"
"    <type>hvm</type>"
"  </os>"
"</domain>";
379 380


381 382 383
static const char *defaultNetworkXML =
"<network>"
"  <name>default</name>"
384
"  <uuid>dd8fe884-6c02-601e-7551-cca97df1c5df</uuid>"
385
"  <bridge name='virbr0'/>"
386 387 388
"  <forward/>"
"  <ip address='192.168.122.1' netmask='255.255.255.0'>"
"    <dhcp>"
389
"      <range start='192.168.122.2' end='192.168.122.254'/>"
390 391 392
"    </dhcp>"
"  </ip>"
"</network>";
393

L
Laine Stump 已提交
394 395 396 397 398 399 400 401 402 403 404
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 已提交
405 406 407
static const char *defaultPoolXML =
"<pool type='dir'>"
"  <name>default-pool</name>"
408
"  <uuid>dfe224cb-28fb-8dd0-c4b2-64eb3f0f4566</uuid>"
C
Cole Robinson 已提交
409 410 411 412 413
"  <target>"
"    <path>/default-pool</path>"
"  </target>"
"</pool>";

414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
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";

437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
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>";

455
static const unsigned long long defaultPoolCap = (100 * 1024 * 1024 * 1024ull);
C
Cole Robinson 已提交
456 457
static const unsigned long long defaultPoolAlloc = 0;

458
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool);
459
static int testNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
460

461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
static virDomainObjPtr
testDomObjFromDomain(virDomainPtr domain)
{
    virDomainObjPtr vm;
    testConnPtr driver = domain->conn->privateData;
    char uuidstr[VIR_UUID_STRING_BUFLEN];

    testDriverLock(driver);
    vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
    if (!vm) {
        virUUIDFormat(domain->uuid, uuidstr);
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching uuid '%s' (%s)"),
                       uuidstr, domain->name);
    }

    testDriverUnlock(driver);
    return vm;
}

481
static char *
482
testDomainGenerateIfname(virDomainDefPtr domdef) {
483
    int maxif = 1024;
484 485
    int ifctr;
    size_t i;
486 487 488 489 490

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

491
        if (virAsprintf(&ifname, "testnet%d", ifctr) < 0)
492 493 494
            return NULL;

        /* Generate network interface names */
495
        for (i = 0; i < domdef->nnets; i++) {
496
            if (domdef->nets[i]->ifname &&
497
                STREQ(domdef->nets[i]->ifname, ifname)) {
498 499 500 501 502 503 504 505 506
                found = 1;
                break;
            }
        }

        if (!found)
            return ifname;
    }

507 508
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Exceeded max iface limit %d"), maxif);
509 510 511
    return NULL;
}

512
static int
513
testDomainGenerateIfnames(virDomainDefPtr domdef)
514
{
515
    size_t i = 0;
516 517 518 519 520 521

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

522
        ifname = testDomainGenerateIfname(domdef);
523
        if (!ifname)
524
            return -1;
525 526 527 528

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

529
    return 0;
530 531
}

532 533
/* Helper to update info for a single VCPU */
static int
534
testDomainUpdateVCPU(virDomainObjPtr dom,
535 536 537 538 539 540 541
                     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);
542
    size_t j;
H
Hu Tao 已提交
543
    bool cpu;
544 545 546 547 548 549 550 551 552 553 554

    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 已提交
555 556 557
            if (virBitmapGetBit(dom->def->cpumask, j, &cpu) < 0)
                return -1;
            if (cpu) {
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
                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
584
testDomainUpdateVCPUs(testConnPtr privconn,
585 586 587 588 589
                      virDomainObjPtr dom,
                      int nvcpus,
                      unsigned int clear_all)
{
    testDomainObjPrivatePtr privdata = dom->privateData;
590 591
    size_t i;
    int ret = -1;
592 593 594 595 596
    int cpumaplen, maxcpu;

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

597
    if (VIR_REALLOC_N(privdata->vcpu_infos, nvcpus) < 0)
598 599
        goto cleanup;

600
    if (VIR_REALLOC_N(privdata->cpumaps, nvcpus * cpumaplen) < 0)
601 602 603 604 605
        goto cleanup;

    /* Set running VCPU and cpumap state */
    if (clear_all) {
        for (i = 0; i < nvcpus; ++i)
606
            if (testDomainUpdateVCPU(dom, i, cpumaplen, maxcpu) < 0)
607 608 609 610 611
                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)
612
            if (testDomainUpdateVCPU(dom, i, cpumaplen, maxcpu) < 0)
613 614 615
                goto cleanup;
    }

616
    dom->def->vcpus = nvcpus;
617 618 619 620 621
    ret = 0;
cleanup:
    return ret;
}

622 623
static void
testDomainShutdownState(virDomainPtr domain,
J
Jiri Denemark 已提交
624 625
                        virDomainObjPtr privdom,
                        virDomainShutoffReason reason)
626 627 628 629 630 631 632
{
    if (privdom->newDef) {
        virDomainDefFree(privdom->def);
        privdom->def = privdom->newDef;
        privdom->newDef = NULL;
    }

J
Jiri Denemark 已提交
633
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF, reason);
634 635 636 637 638
    privdom->def->id = -1;
    if (domain)
        domain->id = -1;
}

639
/* Set up domain runtime state */
640
static int
641
testDomainStartState(testConnPtr privconn,
J
Jiri Denemark 已提交
642 643
                     virDomainObjPtr dom,
                     virDomainRunningReason reason)
644
{
645
    int ret = -1;
646

647
    if (testDomainUpdateVCPUs(privconn, dom, dom->def->vcpus, 1) < 0)
648 649
        goto cleanup;

J
Jiri Denemark 已提交
650
    virDomainObjSetState(dom, VIR_DOMAIN_RUNNING, reason);
651 652
    dom->def->id = privconn->nextDomID++;

653
    if (virDomainObjSetDefTransient(privconn->caps,
654
                                    privconn->xmlopt,
655
                                    dom, false) < 0) {
656 657 658
        goto cleanup;
    }

C
Cole Robinson 已提交
659
    dom->hasManagedSave = false;
660 661
    ret = 0;
cleanup:
662
    if (ret < 0)
J
Jiri Denemark 已提交
663
        testDomainShutdownState(NULL, dom, VIR_DOMAIN_SHUTOFF_FAILED);
664
    return ret;
665
}
666

667
static int testOpenDefault(virConnectPtr conn) {
668
    int u;
669
    testConnPtr privconn;
670 671 672 673
    virDomainDefPtr domdef = NULL;
    virDomainObjPtr domobj = NULL;
    virNetworkDefPtr netdef = NULL;
    virNetworkObjPtr netobj = NULL;
L
Laine Stump 已提交
674 675
    virInterfaceDefPtr interfacedef = NULL;
    virInterfaceObjPtr interfaceobj = NULL;
C
Cole Robinson 已提交
676 677
    virStoragePoolDefPtr pooldef = NULL;
    virStoragePoolObjPtr poolobj = NULL;
678 679
    virNodeDeviceDefPtr nodedef = NULL;
    virNodeDeviceObjPtr nodeobj = NULL;
680

681
    if (VIR_ALLOC(privconn) < 0)
682
        return VIR_DRV_OPEN_ERROR;
683
    if (virMutexInit(&privconn->lock) < 0) {
684 685
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot initialize mutex"));
686 687 688 689
        VIR_FREE(privconn);
        return VIR_DRV_OPEN_ERROR;
    }

690
    testDriverLock(privconn);
691
    conn->privateData = privconn;
692

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

696
    memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));
697

698
    /* Numa setup */
699 700 701 702 703
    privconn->numCells = 2;
    for (u = 0; u < 2; ++u) {
        privconn->cells[u].numCpus = 8;
        privconn->cells[u].mem = (u + 1) * 2048 * 1024;
    }
704
    for (u = 0; u < 16; u++) {
705
        virBitmapPtr siblings = virBitmapNew(16);
706
        if (!siblings)
707 708 709 710 711 712
            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;
713 714
    }

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

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

721 722
    privconn->nextDomID = 1;

723 724
    if (!(domdef = virDomainDefParseString(defaultDomainXML,
                                           privconn->caps,
725
                                           privconn->xmlopt,
M
Matthias Bolte 已提交
726
                                           1 << VIR_DOMAIN_VIRT_TEST,
727
                                           VIR_DOMAIN_XML_INACTIVE)))
728
        goto error;
M
Matthias Bolte 已提交
729

730
    if (testDomainGenerateIfnames(domdef) < 0)
731
        goto error;
732
    if (!(domobj = virDomainObjListAdd(privconn->domains,
733
                                       domdef,
734
                                       privconn->xmlopt,
735
                                       0, NULL)))
736 737
        goto error;
    domdef = NULL;
738

739
    domobj->persistent = 1;
740 741
    if (testDomainStartState(privconn, domobj,
                             VIR_DOMAIN_RUNNING_BOOTED) < 0) {
742
        virObjectUnlock(domobj);
743 744 745
        goto error;
    }

746
    virObjectUnlock(domobj);
747

748
    if (!(netdef = virNetworkDefParseString(defaultNetworkXML)))
749
        goto error;
750
    if (!(netobj = virNetworkAssignDef(&privconn->networks, netdef, false))) {
751 752 753 754 755
        virNetworkDefFree(netdef);
        goto error;
    }
    netobj->active = 1;
    netobj->persistent = 1;
756
    virNetworkObjUnlock(netobj);
757

758
    if (!(interfacedef = virInterfaceDefParseString(defaultInterfaceXML)))
L
Laine Stump 已提交
759
        goto error;
760
    if (!(interfaceobj = virInterfaceAssignDef(&privconn->ifaces, interfacedef))) {
L
Laine Stump 已提交
761 762 763 764 765 766
        virInterfaceDefFree(interfacedef);
        goto error;
    }
    interfaceobj->active = 1;
    virInterfaceObjUnlock(interfaceobj);

767
    if (!(pooldef = virStoragePoolDefParseString(defaultPoolXML)))
C
Cole Robinson 已提交
768 769
        goto error;

770
    if (!(poolobj = virStoragePoolObjAssignDef(&privconn->pools,
C
Cole Robinson 已提交
771 772 773 774
                                               pooldef))) {
        virStoragePoolDefFree(pooldef);
        goto error;
    }
775

776
    if (testStoragePoolObjSetDefaults(poolobj) == -1) {
777
        virStoragePoolObjUnlock(poolobj);
C
Cole Robinson 已提交
778
        goto error;
779
    }
C
Cole Robinson 已提交
780
    poolobj->active = 1;
781
    virStoragePoolObjUnlock(poolobj);
C
Cole Robinson 已提交
782

783
    /* Init default node device */
784
    if (!(nodedef = virNodeDeviceDefParseString(defaultNodeXML, 0, NULL)))
785
        goto error;
786
    if (!(nodeobj = virNodeDeviceAssignDef(&privconn->devs,
787 788 789 790 791 792
                                           nodedef))) {
        virNodeDeviceDefFree(nodedef);
        goto error;
    }
    virNodeDeviceObjUnlock(nodeobj);

793
    testDriverUnlock(privconn);
794

795 796 797
    return VIR_DRV_OPEN_SUCCESS;

error:
798
    virObjectUnref(privconn->domains);
799
    virNetworkObjListFree(&privconn->networks);
L
Laine Stump 已提交
800
    virInterfaceObjListFree(&privconn->ifaces);
C
Cole Robinson 已提交
801
    virStoragePoolObjListFree(&privconn->pools);
802
    virNodeDeviceObjListFree(&privconn->devs);
803
    virObjectUnref(privconn->caps);
804
    testDriverUnlock(privconn);
805
    conn->privateData = NULL;
806
    VIR_FREE(privconn);
807
    virDomainDefFree(domdef);
808
    return VIR_DRV_OPEN_ERROR;
809 810 811 812
}


static char *testBuildFilename(const char *relativeTo,
813 814 815
                               const char *filename) {
    char *offset;
    int baseLen;
816 817
    char *ret;

818
    if (!filename || filename[0] == '\0')
819
        return NULL;
820 821 822 823
    if (filename[0] == '/') {
        ignore_value(VIR_STRDUP(ret, filename));
        return ret;
    }
824

825
    offset = strrchr(relativeTo, '/');
826
    if ((baseLen = (offset-relativeTo+1))) {
827
        char *absFile;
C
Chris Lalancette 已提交
828 829
        int totalLen = baseLen + strlen(filename) + 1;
        if (VIR_ALLOC_N(absFile, totalLen) < 0)
830
            return NULL;
C
Chris Lalancette 已提交
831 832 833 834
        if (virStrncpy(absFile, relativeTo, baseLen, totalLen) == NULL) {
            VIR_FREE(absFile);
            return NULL;
        }
835 836 837
        strcat(absFile, filename);
        return absFile;
    } else {
838 839
        ignore_value(VIR_STRDUP(ret, filename));
        return ret;
840
    }
841 842
}

C
Cole Robinson 已提交
843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879
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;
}

880 881 882
static int
testParseNodeInfo(virNodeInfoPtr nodeInfo, xmlXPathContextPtr ctxt)
{
883
    char *str;
884 885
    long l;
    int ret;
886

887
    ret = virXPathLong("string(/node/cpu/nodes[1])", ctxt, &l);
888 889 890
    if (ret == 0) {
        nodeInfo->nodes = l;
    } else if (ret == -2) {
891 892
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu nodes value"));
893
        goto error;
894
    }
895

896
    ret = virXPathLong("string(/node/cpu/sockets[1])", ctxt, &l);
897 898 899
    if (ret == 0) {
        nodeInfo->sockets = l;
    } else if (ret == -2) {
900 901
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu sockets value"));
902
        goto error;
903
    }
904

905
    ret = virXPathLong("string(/node/cpu/cores[1])", ctxt, &l);
906 907 908
    if (ret == 0) {
        nodeInfo->cores = l;
    } else if (ret == -2) {
909 910
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu cores value"));
911
        goto error;
912 913
    }

914
    ret = virXPathLong("string(/node/cpu/threads[1])", ctxt, &l);
915 916 917
    if (ret == 0) {
        nodeInfo->threads = l;
    } else if (ret == -2) {
918 919
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu threads value"));
920
        goto error;
921
    }
922

923 924
    nodeInfo->cpus = (nodeInfo->cores * nodeInfo->threads *
                      nodeInfo->sockets * nodeInfo->nodes);
925
    ret = virXPathLong("string(/node/cpu/active[1])", ctxt, &l);
926 927
    if (ret == 0) {
        if (l < nodeInfo->cpus) {
928 929
            nodeInfo->cpus = l;
        }
930
    } else if (ret == -2) {
931 932
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu active value"));
933
        goto error;
934
    }
935
    ret = virXPathLong("string(/node/cpu/mhz[1])", ctxt, &l);
936 937 938
    if (ret == 0) {
        nodeInfo->mhz = l;
    } else if (ret == -2) {
939 940
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu mhz value"));
941
        goto error;
942 943
    }

944
    str = virXPathString("string(/node/cpu/model[1])", ctxt);
945
    if (str != NULL) {
C
Chris Lalancette 已提交
946
        if (virStrcpyStatic(nodeInfo->model, str) == NULL) {
947 948
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Model %s too big for destination"), str);
C
Chris Lalancette 已提交
949 950 951
            VIR_FREE(str);
            goto error;
        }
952
        VIR_FREE(str);
953 954
    }

955
    ret = virXPathLong("string(/node/memory[1])", ctxt, &l);
956 957 958
    if (ret == 0) {
        nodeInfo->memory = l;
    } else if (ret == -2) {
959 960
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node memory value"));
961
        goto error;
962
    }
963

964 965 966 967 968
    return 0;
error:
    return -1;
}

969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
static int
testParseDomainSnapshots(testConnPtr privconn,
                         virDomainObjPtr domobj,
                         const char *file,
                         xmlXPathContextPtr ctxt)
{
    size_t i;
    int ret = -1;
    testDomainNamespaceDefPtr nsdata = domobj->def->namespaceData;
    xmlNodePtr *nodes = nsdata->snap_nodes;

    for (i = 0; i < nsdata->num_snap_nodes; i++) {
        virDomainSnapshotObjPtr snap;
        virDomainSnapshotDefPtr def;
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                  "domainsnapshot");
        if (!node)
            goto error;

        def = virDomainSnapshotDefParseNode(ctxt->doc, node,
                                            privconn->caps,
                                            privconn->xmlopt,
                                            1 << VIR_DOMAIN_VIRT_TEST,
                                            VIR_DOMAIN_SNAPSHOT_PARSE_DISKS |
                                            VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL |
                                            VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE);
        if (!def)
            goto error;

        if (!(snap = virDomainSnapshotAssignDef(domobj->snapshots, def))) {
            virDomainSnapshotDefFree(def);
            goto error;
        }

        if (def->current) {
            if (domobj->current_snapshot) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("more than one snapshot claims to be active"));
                goto error;
            }

            domobj->current_snapshot = snap;
        }
    }

    if (virDomainSnapshotUpdateRelations(domobj->snapshots) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Snapshots have inconsistent relations for "
                         "domain %s"), domobj->def->name);
        goto error;
    }

    ret = 0;
error:
    return ret;
}

1026
static int
C
Cole Robinson 已提交
1027 1028 1029
testParseDomains(testConnPtr privconn,
                 const char *file,
                 xmlXPathContextPtr ctxt)
1030 1031 1032 1033 1034 1035 1036 1037
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virDomainObjPtr obj;

    num = virXPathNodeSet("/node/domain", ctxt, &nodes);
    if (num < 0) {
1038
        goto error;
1039
    }
1040

1041
    for (i = 0; i < num; i++) {
1042
        virDomainDefPtr def;
1043
        testDomainNamespaceDefPtr nsdata;
C
Cole Robinson 已提交
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053
        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;
1054

1055
        if (testDomainGenerateIfnames(def) < 0 ||
1056
            !(obj = virDomainObjListAdd(privconn->domains,
1057
                                        def,
1058
                                        privconn->xmlopt,
1059
                                        0, NULL))) {
1060
            virDomainDefFree(def);
1061 1062
            goto error;
        }
1063

1064 1065 1066 1067 1068
        if (testParseDomainSnapshots(privconn, obj, file, ctxt) < 0) {
            virObjectUnlock(obj);
            goto error;
        }

1069
        nsdata = def->namespaceData;
1070
        obj->persistent = !nsdata->transient;
C
Cole Robinson 已提交
1071
        obj->hasManagedSave = nsdata->hasManagedSave;
1072 1073 1074 1075 1076 1077 1078 1079 1080

        if (nsdata->runstate != VIR_DOMAIN_SHUTOFF) {
            if (testDomainStartState(privconn, obj,
                                     VIR_DOMAIN_RUNNING_BOOTED) < 0) {
                virObjectUnlock(obj);
                goto error;
            }
        } else {
            testDomainShutdownState(NULL, obj, 0);
1081
        }
1082
        virDomainObjSetState(obj, nsdata->runstate, 0);
1083

1084
        virObjectUnlock(obj);
1085
    }
1086

1087 1088 1089 1090 1091 1092 1093
    ret = 0;
error:
    VIR_FREE(nodes);
    return ret;
}

static int
C
Cole Robinson 已提交
1094 1095 1096
testParseNetworks(testConnPtr privconn,
                  const char *file,
                  xmlXPathContextPtr ctxt)
1097 1098 1099 1100 1101 1102 1103 1104
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virNetworkObjPtr obj;

    num = virXPathNodeSet("/node/network", ctxt, &nodes);
    if (num < 0) {
1105 1106
        goto error;
    }
1107 1108

    for (i = 0; i < num; i++) {
1109
        virNetworkDefPtr def;
C
Cole Robinson 已提交
1110 1111 1112
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file, "network");
        if (!node)
            goto error;
1113

C
Cole Robinson 已提交
1114 1115 1116
        def = virNetworkDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
1117 1118

        if (!(obj = virNetworkAssignDef(&privconn->networks, def, false))) {
1119 1120
            virNetworkDefFree(def);
            goto error;
1121
        }
1122 1123 1124 1125

        obj->persistent = 1;
        obj->active = 1;
        virNetworkObjUnlock(obj);
1126
    }
1127

1128 1129 1130 1131 1132 1133 1134
    ret = 0;
error:
    VIR_FREE(nodes);
    return ret;
}

static int
C
Cole Robinson 已提交
1135 1136 1137
testParseInterfaces(testConnPtr privconn,
                    const char *file,
                    xmlXPathContextPtr ctxt)
1138 1139 1140 1141 1142 1143 1144 1145
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virInterfaceObjPtr obj;

    num = virXPathNodeSet("/node/interface", ctxt, &nodes);
    if (num < 0) {
L
Laine Stump 已提交
1146 1147
        goto error;
    }
1148 1149

    for (i = 0; i < num; i++) {
L
Laine Stump 已提交
1150
        virInterfaceDefPtr def;
C
Cole Robinson 已提交
1151 1152 1153 1154
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "interface");
        if (!node)
            goto error;
L
Laine Stump 已提交
1155

C
Cole Robinson 已提交
1156 1157 1158
        def = virInterfaceDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
1159

1160
        if (!(obj = virInterfaceAssignDef(&privconn->ifaces, def))) {
L
Laine Stump 已提交
1161 1162 1163
            virInterfaceDefFree(def);
            goto error;
        }
1164

1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175
        obj->active = 1;
        virInterfaceObjUnlock(obj);
    }

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

static int
C
Cole Robinson 已提交
1176
testOpenVolumesForPool(const char *file,
1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197
                       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 已提交
1198 1199 1200 1201
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "volume");
        if (!node)
            goto error;
1202

C
Cole Robinson 已提交
1203 1204 1205
        def = virStorageVolDefParseNode(pool->def, ctxt->doc, node);
        if (!def)
            goto error;
1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226

        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 已提交
1227 1228
    }

1229 1230 1231 1232 1233 1234 1235 1236
    ret = 0;
error:
    virStorageVolDefFree(def);
    VIR_FREE(nodes);
    return ret;
}

static int
C
Cole Robinson 已提交
1237 1238 1239
testParseStorage(testConnPtr privconn,
                 const char *file,
                 xmlXPathContextPtr ctxt)
1240 1241 1242 1243 1244 1245 1246 1247
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virStoragePoolObjPtr obj;

    num = virXPathNodeSet("/node/pool", ctxt, &nodes);
    if (num < 0) {
C
Cole Robinson 已提交
1248 1249
        goto error;
    }
1250 1251

    for (i = 0; i < num; i++) {
C
Cole Robinson 已提交
1252
        virStoragePoolDefPtr def;
C
Cole Robinson 已提交
1253 1254 1255 1256
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "pool");
        if (!node)
            goto error;
C
Cole Robinson 已提交
1257

C
Cole Robinson 已提交
1258 1259 1260
        def = virStoragePoolDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
C
Cole Robinson 已提交
1261

1262
        if (!(obj = virStoragePoolObjAssignDef(&privconn->pools,
C
Cole Robinson 已提交
1263 1264 1265 1266 1267
                                                def))) {
            virStoragePoolDefFree(def);
            goto error;
        }

1268 1269
        if (testStoragePoolObjSetDefaults(obj) == -1) {
            virStoragePoolObjUnlock(obj);
C
Cole Robinson 已提交
1270
            goto error;
1271
        }
1272
        obj->active = 1;
1273 1274

        /* Find storage volumes */
C
Cole Robinson 已提交
1275
        if (testOpenVolumesForPool(file, ctxt, obj, i+1) < 0) {
1276
            virStoragePoolObjUnlock(obj);
1277 1278 1279
            goto error;
        }

1280
        virStoragePoolObjUnlock(obj);
C
Cole Robinson 已提交
1281 1282
    }

1283 1284 1285 1286 1287 1288 1289
    ret = 0;
error:
    VIR_FREE(nodes);
    return ret;
}

static int
C
Cole Robinson 已提交
1290 1291 1292
testParseNodedevs(testConnPtr privconn,
                  const char *file,
                  xmlXPathContextPtr ctxt)
1293 1294 1295 1296 1297 1298 1299 1300
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virNodeDeviceObjPtr obj;

    num = virXPathNodeSet("/node/device", ctxt, &nodes);
    if (num < 0) {
1301 1302
        goto error;
    }
1303 1304

    for (i = 0; i < num; i++) {
1305
        virNodeDeviceDefPtr def;
C
Cole Robinson 已提交
1306 1307 1308 1309
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                  "nodedev");
        if (!node)
            goto error;
1310

C
Cole Robinson 已提交
1311 1312 1313
        def = virNodeDeviceDefParseNode(ctxt->doc, node, 0, NULL);
        if (!def)
            goto error;
1314 1315

        if (!(obj = virNodeDeviceAssignDef(&privconn->devs, def))) {
1316 1317 1318
            virNodeDeviceDefFree(def);
            goto error;
        }
1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342

        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;
1343 1344
    }

1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374
    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 已提交
1375
    if (testParseDomains(privconn, file, ctxt) < 0)
1376
        goto error;
C
Cole Robinson 已提交
1377
    if (testParseNetworks(privconn, file, ctxt) < 0)
1378
        goto error;
C
Cole Robinson 已提交
1379
    if (testParseInterfaces(privconn, file, ctxt) < 0)
1380
        goto error;
C
Cole Robinson 已提交
1381
    if (testParseStorage(privconn, file, ctxt) < 0)
1382
        goto error;
C
Cole Robinson 已提交
1383
    if (testParseNodedevs(privconn, file, ctxt) < 0)
1384
        goto error;
1385

J
Jim Meyering 已提交
1386
    xmlXPathFreeContext(ctxt);
1387
    xmlFreeDoc(doc);
1388
    testDriverUnlock(privconn);
1389

1390
    return 0;
1391 1392

 error:
J
Jim Meyering 已提交
1393
    xmlXPathFreeContext(ctxt);
1394
    xmlFreeDoc(doc);
1395
    virObjectUnref(privconn->domains);
1396
    virNetworkObjListFree(&privconn->networks);
L
Laine Stump 已提交
1397
    virInterfaceObjListFree(&privconn->ifaces);
C
Cole Robinson 已提交
1398
    virStoragePoolObjListFree(&privconn->pools);
E
Eric Blake 已提交
1399
    VIR_FREE(privconn->path);
1400
    testDriverUnlock(privconn);
1401
    VIR_FREE(privconn);
1402
    conn->privateData = NULL;
1403
    return VIR_DRV_OPEN_ERROR;
1404 1405
}

1406

1407 1408 1409
static virDrvOpenStatus testConnectOpen(virConnectPtr conn,
                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                        unsigned int flags)
1410
{
1411
    int ret;
1412
    testConnPtr privconn;
1413

E
Eric Blake 已提交
1414 1415
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

1416
    if (!conn->uri)
1417
        return VIR_DRV_OPEN_DECLINED;
1418

1419
    if (!conn->uri->scheme || STRNEQ(conn->uri->scheme, "test"))
1420
        return VIR_DRV_OPEN_DECLINED;
1421

1422
    /* Remote driver should handle these. */
1423
    if (conn->uri->server)
1424 1425
        return VIR_DRV_OPEN_DECLINED;

1426
    /* From this point on, the connection is for us. */
1427 1428 1429
    if (!conn->uri->path
        || conn->uri->path[0] == '\0'
        || (conn->uri->path[0] == '/' && conn->uri->path[1] == '\0')) {
1430 1431
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("testOpen: supply a path or use test:///default"));
1432 1433
        return VIR_DRV_OPEN_ERROR;
    }
1434

1435
    if (STREQ(conn->uri->path, "/default"))
1436 1437
        ret = testOpenDefault(conn);
    else
1438
        ret = testOpenFromFile(conn,
1439
                               conn->uri->path);
1440

1441 1442 1443 1444 1445
    if (ret != VIR_DRV_OPEN_SUCCESS)
        return ret;

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

1447
    privconn->domainEventState = virDomainEventStateNew();
1448
    if (!privconn->domainEventState) {
1449
        testDriverUnlock(privconn);
1450
        testConnectClose(conn);
1451
        return VIR_DRV_OPEN_ERROR;
1452 1453
    }

1454 1455 1456
    testDriverUnlock(privconn);

    return VIR_DRV_OPEN_SUCCESS;
1457 1458
}

1459
static int testConnectClose(virConnectPtr conn)
1460
{
1461
    testConnPtr privconn = conn->privateData;
1462
    testDriverLock(privconn);
1463
    virObjectUnref(privconn->caps);
1464
    virObjectUnref(privconn->xmlopt);
1465
    virObjectUnref(privconn->domains);
D
Daniel P. Berrange 已提交
1466
    virNodeDeviceObjListFree(&privconn->devs);
1467
    virNetworkObjListFree(&privconn->networks);
L
Laine Stump 已提交
1468
    virInterfaceObjListFree(&privconn->ifaces);
C
Cole Robinson 已提交
1469
    virStoragePoolObjListFree(&privconn->pools);
1470
    virDomainEventStateFree(privconn->domainEventState);
E
Eric Blake 已提交
1471
    VIR_FREE(privconn->path);
1472

1473
    testDriverUnlock(privconn);
1474
    virMutexDestroy(&privconn->lock);
1475

1476
    VIR_FREE(privconn);
1477
    conn->privateData = NULL;
1478
    return 0;
1479 1480
}

1481 1482
static int testConnectGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
                                 unsigned long *hvVer)
1483
{
1484
    *hvVer = 2;
1485
    return 0;
1486 1487
}

1488 1489 1490 1491 1492 1493
static char *testConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return virGetHostname();
}


1494
static int testConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
1495 1496 1497 1498
{
    return 1;
}

1499
static int testConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
1500 1501 1502 1503
{
    return 0;
}

1504
static int testConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
1505 1506 1507 1508
{
    return 1;
}

1509 1510
static int testConnectGetMaxVcpus(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type ATTRIBUTE_UNUSED)
1511 1512 1513 1514 1515 1516
{
    return 32;
}

static int testNodeGetInfo(virConnectPtr conn,
                           virNodeInfoPtr info)
1517
{
1518
    testConnPtr privconn = conn->privateData;
1519
    testDriverLock(privconn);
1520
    memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo));
1521
    testDriverUnlock(privconn);
1522
    return 0;
1523 1524
}

1525
static char *testConnectGetCapabilities(virConnectPtr conn)
1526
{
1527
    testConnPtr privconn = conn->privateData;
1528
    char *xml;
1529
    testDriverLock(privconn);
1530
    if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL)
1531
        virReportOOMError();
1532
    testDriverUnlock(privconn);
1533
    return xml;
1534 1535
}

1536
static int testConnectNumOfDomains(virConnectPtr conn)
1537
{
1538
    testConnPtr privconn = conn->privateData;
1539
    int count;
1540

1541
    testDriverLock(privconn);
1542
    count = virDomainObjListNumOfDomains(privconn->domains, true, NULL, NULL);
1543
    testDriverUnlock(privconn);
1544

1545
    return count;
1546 1547
}

1548 1549 1550 1551 1552 1553 1554
static int testDomainIsActive(virDomainPtr dom)
{
    testConnPtr privconn = dom->conn->privateData;
    virDomainObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
1555
    obj = virDomainObjListFindByUUID(privconn->domains, dom->uuid);
1556 1557
    testDriverUnlock(privconn);
    if (!obj) {
1558
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1559 1560 1561 1562 1563 1564
        goto cleanup;
    }
    ret = virDomainObjIsActive(obj);

cleanup:
    if (obj)
1565
        virObjectUnlock(obj);
1566 1567 1568 1569 1570 1571 1572 1573 1574 1575
    return ret;
}

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

    testDriverLock(privconn);
1576
    obj = virDomainObjListFindByUUID(privconn->domains, dom->uuid);
1577 1578
    testDriverUnlock(privconn);
    if (!obj) {
1579
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1580 1581 1582 1583 1584 1585
        goto cleanup;
    }
    ret = obj->persistent;

cleanup:
    if (obj)
1586
        virObjectUnlock(obj);
1587 1588 1589
    return ret;
}

1590 1591 1592 1593 1594
static int testDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
{
    return 0;
}

1595
static virDomainPtr
1596
testDomainCreateXML(virConnectPtr conn, const char *xml,
1597
                      unsigned int flags)
1598
{
1599
    testConnPtr privconn = conn->privateData;
1600
    virDomainPtr ret = NULL;
1601
    virDomainDefPtr def;
1602
    virDomainObjPtr dom = NULL;
1603
    virDomainEventPtr event = NULL;
1604

1605 1606
    virCheckFlags(0, NULL);

1607
    testDriverLock(privconn);
1608 1609
    if ((def = virDomainDefParseString(xml,privconn->caps, privconn->xmlopt,
                                       1 << VIR_DOMAIN_VIRT_TEST,
1610
                                       VIR_DOMAIN_XML_INACTIVE)) == NULL)
1611
        goto cleanup;
1612

1613
    if (testDomainGenerateIfnames(def) < 0)
1614
        goto cleanup;
1615
    if (!(dom = virDomainObjListAdd(privconn->domains,
1616
                                    def,
1617
                                    privconn->xmlopt,
1618 1619
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
1620 1621
        goto cleanup;
    def = NULL;
1622

1623
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_BOOTED) < 0)
1624
        goto cleanup;
1625

1626 1627 1628 1629
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);

1630
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1631
    if (ret)
1632
        ret->id = dom->def->id;
1633 1634

cleanup:
1635
    if (dom)
1636
        virObjectUnlock(dom);
1637 1638
    if (event)
        testDomainEventQueue(privconn, event);
1639
    virDomainDefFree(def);
1640
    testDriverUnlock(privconn);
1641
    return ret;
1642 1643 1644
}


1645
static virDomainPtr testDomainLookupByID(virConnectPtr conn,
1646
                                         int id)
1647
{
1648
    testConnPtr privconn = conn->privateData;
1649 1650
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1651

1652
    testDriverLock(privconn);
1653
    dom = virDomainObjListFindByID(privconn->domains, id);
1654 1655 1656
    testDriverUnlock(privconn);

    if (dom == NULL) {
1657
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1658
        goto cleanup;
1659 1660
    }

1661
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1662 1663 1664 1665
    if (ret)
        ret->id = dom->def->id;

cleanup:
1666
    if (dom)
1667
        virObjectUnlock(dom);
1668
    return ret;
1669 1670
}

1671
static virDomainPtr testDomainLookupByUUID(virConnectPtr conn,
1672
                                           const unsigned char *uuid)
1673
{
1674
    testConnPtr privconn = conn->privateData;
1675
    virDomainPtr ret = NULL;
1676
    virDomainObjPtr dom;
1677

1678
    testDriverLock(privconn);
1679
    dom = virDomainObjListFindByUUID(privconn->domains, uuid);
1680 1681 1682
    testDriverUnlock(privconn);

    if (dom == NULL) {
1683
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1684
        goto cleanup;
1685
    }
1686

1687
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1688 1689 1690 1691
    if (ret)
        ret->id = dom->def->id;

cleanup:
1692
    if (dom)
1693
        virObjectUnlock(dom);
1694
    return ret;
1695 1696
}

1697
static virDomainPtr testDomainLookupByName(virConnectPtr conn,
1698
                                           const char *name)
1699
{
1700
    testConnPtr privconn = conn->privateData;
1701 1702
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1703

1704
    testDriverLock(privconn);
1705
    dom = virDomainObjListFindByName(privconn->domains, name);
1706 1707 1708
    testDriverUnlock(privconn);

    if (dom == NULL) {
1709
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1710
        goto cleanup;
1711
    }
1712

1713
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1714 1715 1716 1717
    if (ret)
        ret->id = dom->def->id;

cleanup:
1718
    if (dom)
1719
        virObjectUnlock(dom);
1720
    return ret;
1721 1722
}

1723 1724 1725
static int testConnectListDomains(virConnectPtr conn,
                                  int *ids,
                                  int maxids)
1726
{
1727
    testConnPtr privconn = conn->privateData;
1728
    int n;
1729

1730
    testDriverLock(privconn);
1731
    n = virDomainObjListGetActiveIDs(privconn->domains, ids, maxids, NULL, NULL);
1732
    testDriverUnlock(privconn);
1733

1734
    return n;
1735 1736
}

1737
static int testDomainDestroy(virDomainPtr domain)
1738
{
1739 1740
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1741
    virDomainEventPtr event = NULL;
1742
    int ret = -1;
1743

1744
    testDriverLock(privconn);
1745 1746
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1747 1748

    if (privdom == NULL) {
1749
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1750
        goto cleanup;
1751
    }
1752

J
Jiri Denemark 已提交
1753
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_DESTROYED);
1754 1755 1756
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
1757

1758
    if (!privdom->persistent) {
1759 1760
        virDomainObjListRemove(privconn->domains,
                               privdom);
1761
        privdom = NULL;
1762
    }
1763 1764 1765

    ret = 0;
cleanup:
1766
    if (privdom)
1767
        virObjectUnlock(privdom);
1768 1769
    if (event)
        testDomainEventQueue(privconn, event);
1770
    testDriverUnlock(privconn);
1771
    return ret;
1772 1773
}

1774
static int testDomainResume(virDomainPtr domain)
1775
{
1776 1777
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1778
    virDomainEventPtr event = NULL;
1779
    int ret = -1;
1780

1781
    testDriverLock(privconn);
1782 1783
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1784
    testDriverUnlock(privconn);
1785 1786

    if (privdom == NULL) {
1787
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1788
        goto cleanup;
1789
    }
1790

J
Jiri Denemark 已提交
1791
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_PAUSED) {
1792 1793
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"),
                       domain->name);
1794
        goto cleanup;
1795
    }
1796

J
Jiri Denemark 已提交
1797 1798
    virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                         VIR_DOMAIN_RUNNING_UNPAUSED);
1799 1800 1801
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_RESUMED,
                                     VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
1802 1803 1804
    ret = 0;

cleanup:
1805
    if (privdom)
1806
        virObjectUnlock(privdom);
1807 1808 1809 1810 1811
    if (event) {
        testDriverLock(privconn);
        testDomainEventQueue(privconn, event);
        testDriverUnlock(privconn);
    }
1812
    return ret;
1813 1814
}

1815
static int testDomainSuspend(virDomainPtr domain)
1816
{
1817 1818
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1819
    virDomainEventPtr event = NULL;
1820
    int ret = -1;
J
Jiri Denemark 已提交
1821
    int state;
1822

1823
    testDriverLock(privconn);
1824 1825
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1826
    testDriverUnlock(privconn);
1827 1828

    if (privdom == NULL) {
1829
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1830
        goto cleanup;
1831
    }
1832

J
Jiri Denemark 已提交
1833 1834
    state = virDomainObjGetState(privdom, NULL);
    if (state == VIR_DOMAIN_SHUTOFF || state == VIR_DOMAIN_PAUSED) {
1835 1836
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"),
                       domain->name);
1837
        goto cleanup;
1838
    }
1839

J
Jiri Denemark 已提交
1840
    virDomainObjSetState(privdom, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
1841 1842 1843
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_SUSPENDED,
                                     VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
1844 1845 1846
    ret = 0;

cleanup:
1847
    if (privdom)
1848
        virObjectUnlock(privdom);
1849 1850 1851 1852 1853 1854

    if (event) {
        testDriverLock(privconn);
        testDomainEventQueue(privconn, event);
        testDriverUnlock(privconn);
    }
1855
    return ret;
1856 1857
}

1858
static int testDomainShutdownFlags(virDomainPtr domain,
1859
                                   unsigned int flags)
1860
{
1861 1862
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1863
    virDomainEventPtr event = NULL;
1864
    int ret = -1;
1865

1866 1867
    virCheckFlags(0, -1);

1868
    testDriverLock(privconn);
1869 1870
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1871 1872

    if (privdom == NULL) {
1873
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1874
        goto cleanup;
1875
    }
1876

J
Jiri Denemark 已提交
1877
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
1878 1879
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("domain '%s' not running"), domain->name);
1880
        goto cleanup;
1881
    }
1882

J
Jiri Denemark 已提交
1883
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1884 1885 1886
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1887

1888
    if (!privdom->persistent) {
1889 1890
        virDomainObjListRemove(privconn->domains,
                               privdom);
1891 1892
        privdom = NULL;
    }
1893

1894
    ret = 0;
1895
cleanup:
1896
    if (privdom)
1897
        virObjectUnlock(privdom);
1898 1899
    if (event)
        testDomainEventQueue(privconn, event);
1900
    testDriverUnlock(privconn);
1901
    return ret;
1902 1903
}

1904
static int testDomainShutdown(virDomainPtr domain)
1905
{
1906
    return testDomainShutdownFlags(domain, 0);
1907 1908
}

1909
/* Similar behaviour as shutdown */
1910
static int testDomainReboot(virDomainPtr domain,
1911
                            unsigned int action ATTRIBUTE_UNUSED)
1912
{
1913 1914
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1915
    virDomainEventPtr event = NULL;
1916
    int ret = -1;
1917

1918
    testDriverLock(privconn);
1919 1920
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1921 1922

    if (privdom == NULL) {
1923
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1924
        goto cleanup;
1925
    }
1926

J
Jiri Denemark 已提交
1927 1928 1929
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTDOWN,
                         VIR_DOMAIN_SHUTDOWN_USER);

1930 1931
    switch (privdom->def->onReboot) {
    case VIR_DOMAIN_LIFECYCLE_DESTROY:
J
Jiri Denemark 已提交
1932 1933
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1934 1935
        break;

1936
    case VIR_DOMAIN_LIFECYCLE_RESTART:
J
Jiri Denemark 已提交
1937 1938
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
1939 1940
        break;

1941
    case VIR_DOMAIN_LIFECYCLE_PRESERVE:
J
Jiri Denemark 已提交
1942 1943
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1944 1945
        break;

1946
    case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME:
J
Jiri Denemark 已提交
1947 1948
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
1949
        break;
1950

1951
    default:
J
Jiri Denemark 已提交
1952 1953
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1954 1955
        break;
    }
1956

J
Jiri Denemark 已提交
1957 1958
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1959 1960 1961
        event = virDomainEventNewFromObj(privdom,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1962

1963
        if (!privdom->persistent) {
1964 1965
            virDomainObjListRemove(privconn->domains,
                                   privdom);
1966 1967
            privdom = NULL;
        }
1968 1969
    }

1970 1971
    ret = 0;
cleanup:
1972
    if (privdom)
1973
        virObjectUnlock(privdom);
1974 1975
    if (event)
        testDomainEventQueue(privconn, event);
1976
    testDriverUnlock(privconn);
1977
    return ret;
1978 1979
}

1980
static int testDomainGetInfo(virDomainPtr domain,
1981
                             virDomainInfoPtr info)
1982
{
1983
    testConnPtr privconn = domain->conn->privateData;
1984
    struct timeval tv;
1985
    virDomainObjPtr privdom;
1986
    int ret = -1;
1987

1988
    testDriverLock(privconn);
1989 1990
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1991
    testDriverUnlock(privconn);
1992 1993

    if (privdom == NULL) {
1994
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1995
        goto cleanup;
1996
    }
1997 1998

    if (gettimeofday(&tv, NULL) < 0) {
1999 2000
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("getting time of day"));
2001
        goto cleanup;
2002 2003
    }

J
Jiri Denemark 已提交
2004
    info->state = virDomainObjGetState(privdom, NULL);
2005 2006
    info->memory = privdom->def->mem.cur_balloon;
    info->maxMem = privdom->def->mem.max_balloon;
2007 2008
    info->nrVirtCpu = privdom->def->vcpus;
    info->cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
2009 2010 2011
    ret = 0;

cleanup:
2012
    if (privdom)
2013
        virObjectUnlock(privdom);
2014
    return ret;
2015 2016
}

2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029
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);
2030 2031
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2032 2033 2034
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2035
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2036 2037 2038
        goto cleanup;
    }

J
Jiri Denemark 已提交
2039
    *state = virDomainObjGetState(privdom, reason);
2040 2041 2042 2043
    ret = 0;

cleanup:
    if (privdom)
2044
        virObjectUnlock(privdom);
2045 2046 2047
    return ret;
}

2048 2049
#define TEST_SAVE_MAGIC "TestGuestMagic"

2050 2051 2052
static int
testDomainSaveFlags(virDomainPtr domain, const char *path,
                    const char *dxml, unsigned int flags)
2053
{
2054
    testConnPtr privconn = domain->conn->privateData;
2055 2056 2057
    char *xml = NULL;
    int fd = -1;
    int len;
2058
    virDomainObjPtr privdom;
2059
    virDomainEventPtr event = NULL;
2060
    int ret = -1;
2061

2062 2063
    virCheckFlags(0, -1);
    if (dxml) {
2064 2065
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
2066 2067 2068
        return -1;
    }

2069
    testDriverLock(privconn);
2070 2071
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2072 2073

    if (privdom == NULL) {
2074
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2075
        goto cleanup;
2076
    }
2077

2078
    xml = virDomainDefFormat(privdom->def,
C
Cole Robinson 已提交
2079 2080
                             VIR_DOMAIN_XML_SECURE);

2081
    if (xml == NULL) {
2082
        virReportSystemError(errno,
2083 2084
                             _("saving domain '%s' failed to allocate space for metadata"),
                             domain->name);
2085
        goto cleanup;
2086
    }
2087 2088

    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
2089
        virReportSystemError(errno,
2090 2091
                             _("saving domain '%s' to '%s': open failed"),
                             domain->name, path);
2092
        goto cleanup;
2093
    }
2094
    len = strlen(xml);
2095
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
2096
        virReportSystemError(errno,
2097 2098
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
2099
        goto cleanup;
2100
    }
2101
    if (safewrite(fd, (char*)&len, sizeof(len)) < 0) {
2102
        virReportSystemError(errno,
2103 2104
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
2105
        goto cleanup;
2106
    }
2107
    if (safewrite(fd, xml, len) < 0) {
2108
        virReportSystemError(errno,
2109 2110
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
2111
        goto cleanup;
2112
    }
2113

2114
    if (VIR_CLOSE(fd) < 0) {
2115
        virReportSystemError(errno,
2116 2117
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
2118
        goto cleanup;
2119
    }
2120 2121
    fd = -1;

J
Jiri Denemark 已提交
2122
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SAVED);
2123 2124 2125
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
2126

2127
    if (!privdom->persistent) {
2128 2129
        virDomainObjListRemove(privconn->domains,
                               privdom);
2130
        privdom = NULL;
2131
    }
2132

2133
    ret = 0;
2134 2135 2136 2137 2138 2139 2140
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) {
2141
        VIR_FORCE_CLOSE(fd);
2142 2143
        unlink(path);
    }
2144
    if (privdom)
2145
        virObjectUnlock(privdom);
2146 2147
    if (event)
        testDomainEventQueue(privconn, event);
2148
    testDriverUnlock(privconn);
2149
    return ret;
2150 2151
}

2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163
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)
2164
{
2165
    testConnPtr privconn = conn->privateData;
2166
    char *xml = NULL;
2167
    char magic[15];
2168 2169 2170
    int fd = -1;
    int len;
    virDomainDefPtr def = NULL;
2171
    virDomainObjPtr dom = NULL;
2172
    virDomainEventPtr event = NULL;
2173
    int ret = -1;
2174

2175 2176
    virCheckFlags(0, -1);
    if (dxml) {
2177 2178
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
2179 2180 2181
        return -1;
    }

2182 2183
    testDriverLock(privconn);

2184
    if ((fd = open(path, O_RDONLY)) < 0) {
2185
        virReportSystemError(errno,
2186 2187
                             _("cannot read domain image '%s'"),
                             path);
2188
        goto cleanup;
2189
    }
2190
    if (saferead(fd, magic, sizeof(magic)) != sizeof(magic)) {
2191
        virReportSystemError(errno,
2192 2193
                             _("incomplete save header in '%s'"),
                             path);
2194
        goto cleanup;
2195
    }
2196
    if (memcmp(magic, TEST_SAVE_MAGIC, sizeof(magic))) {
2197 2198
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("mismatched header magic"));
2199
        goto cleanup;
2200
    }
2201
    if (saferead(fd, (char*)&len, sizeof(len)) != sizeof(len)) {
2202
        virReportSystemError(errno,
2203 2204
                             _("failed to read metadata length in '%s'"),
                             path);
2205
        goto cleanup;
2206 2207
    }
    if (len < 1 || len > 8192) {
2208 2209
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("length of metadata out of range"));
2210
        goto cleanup;
2211
    }
2212
    if (VIR_ALLOC_N(xml, len+1) < 0)
2213
        goto cleanup;
2214
    if (saferead(fd, xml, len) != len) {
2215
        virReportSystemError(errno,
2216
                             _("incomplete metadata in '%s'"), path);
2217
        goto cleanup;
2218 2219
    }
    xml[len] = '\0';
2220

2221 2222
    def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
                                  1 << VIR_DOMAIN_VIRT_TEST,
2223
                                  VIR_DOMAIN_XML_INACTIVE);
2224
    if (!def)
2225
        goto cleanup;
2226

2227
    if (testDomainGenerateIfnames(def) < 0)
2228
        goto cleanup;
2229
    if (!(dom = virDomainObjListAdd(privconn->domains,
2230
                                    def,
2231
                                    privconn->xmlopt,
2232 2233 2234
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
2235 2236
        goto cleanup;
    def = NULL;
2237

2238
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_RESTORED) < 0)
2239 2240
        goto cleanup;

2241 2242 2243
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
2244
    ret = 0;
2245 2246 2247 2248

cleanup:
    virDomainDefFree(def);
    VIR_FREE(xml);
2249
    VIR_FORCE_CLOSE(fd);
2250
    if (dom)
2251
        virObjectUnlock(dom);
2252 2253
    if (event)
        testDomainEventQueue(privconn, event);
2254
    testDriverUnlock(privconn);
2255
    return ret;
2256 2257
}

2258 2259 2260 2261 2262 2263 2264
static int
testDomainRestore(virConnectPtr conn,
                  const char *path)
{
    return testDomainRestoreFlags(conn, path, NULL, 0);
}

2265 2266
static int testDomainCoreDump(virDomainPtr domain,
                              const char *to,
E
Eric Blake 已提交
2267
                              unsigned int flags)
2268
{
2269
    testConnPtr privconn = domain->conn->privateData;
2270
    int fd = -1;
2271
    virDomainObjPtr privdom;
2272
    virDomainEventPtr event = NULL;
2273
    int ret = -1;
2274

E
Eric Blake 已提交
2275 2276
    virCheckFlags(VIR_DUMP_CRASH, -1);

2277
    testDriverLock(privconn);
2278 2279
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2280 2281

    if (privdom == NULL) {
2282
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2283
        goto cleanup;
2284
    }
2285 2286

    if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
2287
        virReportSystemError(errno,
2288 2289
                             _("domain '%s' coredump: failed to open %s"),
                             domain->name, to);
2290
        goto cleanup;
2291
    }
2292
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
2293
        virReportSystemError(errno,
2294 2295
                             _("domain '%s' coredump: failed to write header to %s"),
                             domain->name, to);
2296
        goto cleanup;
2297
    }
2298
    if (VIR_CLOSE(fd) < 0) {
2299
        virReportSystemError(errno,
2300 2301
                             _("domain '%s' coredump: write failed: %s"),
                             domain->name, to);
2302
        goto cleanup;
2303
    }
2304

2305
    if (flags & VIR_DUMP_CRASH) {
J
Jiri Denemark 已提交
2306
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_CRASHED);
2307 2308 2309 2310
        event = virDomainEventNewFromObj(privdom,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
        if (!privdom->persistent) {
2311 2312
            virDomainObjListRemove(privconn->domains,
                                   privdom);
2313 2314
            privdom = NULL;
        }
2315
    }
2316

2317
    ret = 0;
2318
cleanup:
2319
    VIR_FORCE_CLOSE(fd);
2320
    if (privdom)
2321
        virObjectUnlock(privdom);
2322 2323
    if (event)
        testDomainEventQueue(privconn, event);
2324
    testDriverUnlock(privconn);
2325
    return ret;
2326 2327
}

2328
static char *testDomainGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) {
2329 2330 2331
    char *ret;

    ignore_value(VIR_STRDUP(ret, "linux"));
2332
    return ret;
2333 2334
}

2335
static unsigned long long testDomainGetMaxMemory(virDomainPtr domain) {
2336 2337
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2338
    unsigned long long ret = 0;
2339

2340
    testDriverLock(privconn);
2341 2342
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2343
    testDriverUnlock(privconn);
2344 2345

    if (privdom == NULL) {
2346
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2347
        goto cleanup;
2348
    }
2349

2350
    ret = privdom->def->mem.max_balloon;
2351 2352

cleanup:
2353
    if (privdom)
2354
        virObjectUnlock(privdom);
2355
    return ret;
2356 2357
}

2358 2359
static int testDomainSetMaxMemory(virDomainPtr domain,
                                  unsigned long memory)
2360
{
2361 2362
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2363
    int ret = -1;
2364

2365
    testDriverLock(privconn);
2366 2367
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2368
    testDriverUnlock(privconn);
2369 2370

    if (privdom == NULL) {
2371
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2372
        goto cleanup;
2373
    }
2374 2375

    /* XXX validate not over host memory wrt to other domains */
2376
    privdom->def->mem.max_balloon = memory;
2377 2378 2379
    ret = 0;

cleanup:
2380
    if (privdom)
2381
        virObjectUnlock(privdom);
2382
    return ret;
2383 2384
}

2385 2386
static int testDomainSetMemory(virDomainPtr domain,
                               unsigned long memory)
2387
{
2388 2389
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2390
    int ret = -1;
2391

2392
    testDriverLock(privconn);
2393 2394
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2395
    testDriverUnlock(privconn);
2396 2397

    if (privdom == NULL) {
2398
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2399
        goto cleanup;
2400
    }
2401

2402
    if (memory > privdom->def->mem.max_balloon) {
2403
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2404
        goto cleanup;
2405
    }
2406

2407
    privdom->def->mem.cur_balloon = memory;
2408 2409 2410
    ret = 0;

cleanup:
2411
    if (privdom)
2412
        virObjectUnlock(privdom);
2413
    return ret;
2414 2415
}

2416 2417
static int
testDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
C
Cole Robinson 已提交
2418
{
2419 2420 2421 2422 2423
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr vm;
    virDomainDefPtr def;
    int ret = -1;

2424 2425
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2426 2427 2428
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

    testDriverLock(privconn);
2429
    vm = virDomainObjListFindByUUID(privconn->domains, domain->uuid);
2430 2431 2432 2433 2434
    testDriverUnlock(privconn);

    if (!vm) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(domain->uuid, uuidstr);
2435 2436
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching uuid '%s'"), uuidstr);
2437 2438 2439
        goto cleanup;
    }

2440
    if (virDomainLiveConfigHelperMethod(privconn->caps, privconn->xmlopt,
2441
                                        vm, &flags, &def) < 0)
2442
        goto cleanup;
2443

2444
    if (flags & VIR_DOMAIN_AFFECT_LIVE)
2445 2446 2447 2448 2449 2450
        def = vm->def;

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

cleanup:
    if (vm)
2451
        virObjectUnlock(vm);
2452
    return ret;
C
Cole Robinson 已提交
2453 2454
}

2455 2456 2457
static int
testDomainGetMaxVcpus(virDomainPtr domain)
{
2458
    return testDomainGetVcpusFlags(domain, (VIR_DOMAIN_AFFECT_LIVE |
2459 2460 2461 2462 2463 2464 2465
                                            VIR_DOMAIN_VCPU_MAXIMUM));
}

static int
testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
                        unsigned int flags)
{
2466
    testConnPtr privconn = domain->conn->privateData;
2467
    virDomainObjPtr privdom = NULL;
2468
    virDomainDefPtr persistentDef;
C
Cole Robinson 已提交
2469 2470
    int ret = -1, maxvcpus;

2471 2472
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2473 2474 2475 2476
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

    /* At least one of LIVE or CONFIG must be set.  MAXIMUM cannot be
     * mixed with LIVE.  */
2477 2478 2479
    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)) {
2480 2481
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
2482 2483
        return -1;
    }
2484
    if (!nrCpus || (maxvcpus = testConnectGetMaxVcpus(domain->conn, NULL)) < nrCpus) {
2485 2486
        virReportError(VIR_ERR_INVALID_ARG,
                       _("argument out of range: %d"), nrCpus);
2487 2488
        return -1;
    }
2489

2490
    testDriverLock(privconn);
2491
    privdom = virDomainObjListFindByUUID(privconn->domains, domain->uuid);
2492 2493 2494
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2495
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2496
        goto cleanup;
2497
    }
2498

2499
    if (!virDomainObjIsActive(privdom) && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
2500 2501
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot hotplug vcpus for an inactive domain"));
C
Cole Robinson 已提交
2502 2503 2504
        goto cleanup;
    }

2505 2506
    /* We allow more cpus in guest than host, but not more than the
     * domain's starting limit.  */
C
Cole Robinson 已提交
2507 2508
    if (!(flags & (VIR_DOMAIN_VCPU_MAXIMUM)) &&
        privdom->def->maxvcpus < maxvcpus)
2509
        maxvcpus = privdom->def->maxvcpus;
C
Cole Robinson 已提交
2510

C
Cole Robinson 已提交
2511
    if (nrCpus > maxvcpus) {
2512 2513 2514
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested cpu amount exceeds maximum (%d > %d)"),
                       nrCpus, maxvcpus);
2515
        goto cleanup;
2516
    }
2517

2518
    if (!(persistentDef = virDomainObjGetPersistentDef(privconn->caps,
2519
                                                       privconn->xmlopt,
2520 2521 2522
                                                       privdom)))
        goto cleanup;

2523
    switch (flags) {
2524
    case VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_AFFECT_CONFIG:
2525 2526 2527
        persistentDef->maxvcpus = nrCpus;
        if (nrCpus < persistentDef->vcpus)
            persistentDef->vcpus = nrCpus;
2528 2529
        ret = 0;
        break;
2530

2531
    case VIR_DOMAIN_AFFECT_CONFIG:
2532
        persistentDef->vcpus = nrCpus;
2533 2534 2535
        ret = 0;
        break;

2536
    case VIR_DOMAIN_AFFECT_LIVE:
2537
        ret = testDomainUpdateVCPUs(privconn, privdom, nrCpus, 0);
2538 2539
        break;

2540
    case VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG:
2541
        ret = testDomainUpdateVCPUs(privconn, privdom, nrCpus, 0);
2542 2543 2544
        if (ret == 0) {
            persistentDef->vcpus = nrCpus;
        }
2545 2546
        break;
    }
2547 2548

cleanup:
2549
    if (privdom)
2550
        virObjectUnlock(privdom);
2551
    return ret;
2552 2553
}

2554
static int
2555
testDomainSetVcpus(virDomainPtr domain, unsigned int nrCpus)
2556
{
2557
    return testDomainSetVcpusFlags(domain, nrCpus, VIR_DOMAIN_AFFECT_LIVE);
2558 2559
}

C
Cole Robinson 已提交
2560 2561 2562 2563 2564 2565 2566 2567 2568
static int testDomainGetVcpus(virDomainPtr domain,
                              virVcpuInfoPtr info,
                              int maxinfo,
                              unsigned char *cpumaps,
                              int maplen)
{
    testConnPtr privconn = domain->conn->privateData;
    testDomainObjPrivatePtr privdomdata;
    virDomainObjPtr privdom;
2569 2570
    size_t i;
    int v, maxcpu, hostcpus;
C
Cole Robinson 已提交
2571 2572 2573 2574 2575
    int ret = -1;
    struct timeval tv;
    unsigned long long statbase;

    testDriverLock(privconn);
2576
    privdom = virDomainObjListFindByName(privconn->domains, domain->name);
C
Cole Robinson 已提交
2577 2578 2579
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2580
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
C
Cole Robinson 已提交
2581 2582 2583 2584
        goto cleanup;
    }

    if (!virDomainObjIsActive(privdom)) {
2585 2586
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s",_("cannot list vcpus for an inactive domain"));
C
Cole Robinson 已提交
2587 2588 2589 2590 2591 2592
        goto cleanup;
    }

    privdomdata = privdom->privateData;

    if (gettimeofday(&tv, NULL) < 0) {
2593
        virReportSystemError(errno,
C
Cole Robinson 已提交
2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613
                             "%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);

2614
        for (i = 0; i < maxinfo; i++) {
C
Cole Robinson 已提交
2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630
            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);

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

2634
            for (i = 0; i < maxcpu; i++) {
C
Cole Robinson 已提交
2635 2636 2637 2638 2639 2640 2641 2642 2643 2644
                if (VIR_CPU_USABLE(privdomdata->cpumaps, privmaplen, v, i)) {
                    VIR_USE_CPU(cpumap, i);
                }
            }
        }
    }

    ret = maxinfo;
cleanup:
    if (privdom)
2645
        virObjectUnlock(privdom);
C
Cole Robinson 已提交
2646 2647 2648
    return ret;
}

C
Cole Robinson 已提交
2649 2650 2651 2652 2653 2654 2655 2656 2657
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;
2658 2659
    size_t i;
    int maxcpu, hostcpus, privmaplen;
C
Cole Robinson 已提交
2660 2661 2662
    int ret = -1;

    testDriverLock(privconn);
2663
    privdom = virDomainObjListFindByName(privconn->domains, domain->name);
C
Cole Robinson 已提交
2664 2665 2666
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2667
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
C
Cole Robinson 已提交
2668 2669 2670 2671
        goto cleanup;
    }

    if (!virDomainObjIsActive(privdom)) {
2672 2673
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s",_("cannot pin vcpus on an inactive domain"));
C
Cole Robinson 已提交
2674 2675 2676 2677
        goto cleanup;
    }

    if (vcpu > privdom->def->vcpus) {
2678 2679
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("requested vcpu is higher than allocated vcpus"));
C
Cole Robinson 已提交
2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693
        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);

2694
    for (i = 0; i < maxcpu; i++) {
C
Cole Robinson 已提交
2695 2696 2697 2698 2699 2700 2701 2702
        if (VIR_CPU_USABLE(cpumap, maplen, 0, i)) {
            VIR_USE_CPU(privcpumap, i);
        }
    }

    ret = 0;
cleanup:
    if (privdom)
2703
        virObjectUnlock(privdom);
C
Cole Robinson 已提交
2704 2705 2706
    return ret;
}

2707
static char *testDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
2708
{
2709
    testConnPtr privconn = domain->conn->privateData;
2710
    virDomainDefPtr def;
2711
    virDomainObjPtr privdom;
2712 2713
    char *ret = NULL;

2714 2715
    /* Flags checked by virDomainDefFormat */

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

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

2726 2727
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
2728

2729
    ret = virDomainDefFormat(def,
2730 2731 2732
                             flags);

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

2738
static int testConnectNumOfDefinedDomains(virConnectPtr conn) {
2739
    testConnPtr privconn = conn->privateData;
2740
    int count;
2741

2742
    testDriverLock(privconn);
2743
    count = virDomainObjListNumOfDomains(privconn->domains, false, NULL, NULL);
2744
    testDriverUnlock(privconn);
2745

2746
    return count;
2747 2748
}

2749 2750 2751
static int testConnectListDefinedDomains(virConnectPtr conn,
                                         char **const names,
                                         int maxnames) {
2752

2753
    testConnPtr privconn = conn->privateData;
2754
    int n;
2755

2756
    testDriverLock(privconn);
2757
    memset(names, 0, sizeof(*names)*maxnames);
2758 2759
    n = virDomainObjListGetInactiveNames(privconn->domains, names, maxnames,
                                         NULL, NULL);
2760
    testDriverUnlock(privconn);
2761

2762
    return n;
2763 2764
}

2765
static virDomainPtr testDomainDefineXML(virConnectPtr conn,
2766
                                        const char *xml) {
2767
    testConnPtr privconn = conn->privateData;
2768
    virDomainPtr ret = NULL;
2769
    virDomainDefPtr def;
2770
    virDomainObjPtr dom = NULL;
2771
    virDomainEventPtr event = NULL;
2772
    virDomainDefPtr oldDef = NULL;
2773

2774
    testDriverLock(privconn);
2775 2776
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
                                       1 << VIR_DOMAIN_VIRT_TEST,
2777
                                       VIR_DOMAIN_XML_INACTIVE)) == NULL)
2778
        goto cleanup;
2779

2780
    if (testDomainGenerateIfnames(def) < 0)
2781
        goto cleanup;
2782
    if (!(dom = virDomainObjListAdd(privconn->domains,
2783
                                    def,
2784
                                    privconn->xmlopt,
2785 2786
                                    0,
                                    &oldDef)))
2787
        goto cleanup;
2788
    def = NULL;
2789
    dom->persistent = 1;
2790

2791 2792
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_DEFINED,
2793
                                     !oldDef ?
2794 2795
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
2796

2797
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
2798
    if (ret)
2799
        ret->id = dom->def->id;
2800 2801 2802

cleanup:
    virDomainDefFree(def);
2803
    virDomainDefFree(oldDef);
2804
    if (dom)
2805
        virObjectUnlock(dom);
2806 2807
    if (event)
        testDomainEventQueue(privconn, event);
2808
    testDriverUnlock(privconn);
2809
    return ret;
2810 2811
}

2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877
static char *testDomainGetMetadata(virDomainPtr dom,
                                   int type,
                                   const char *uri,
                                   unsigned int flags)
{
    testConnPtr privconn = dom->conn->privateData;
    virDomainObjPtr privdom;
    char *ret = NULL;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, NULL);

    testDriverLock(privconn);
    privdom = virDomainObjListFindByName(privconn->domains,
                                         dom->name);
    testDriverUnlock(privconn);

    if (privdom == NULL) {
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
        goto cleanup;
    }

    ret = virDomainObjGetMetadata(privdom, type, uri, privconn->caps,
                                  privconn->xmlopt, flags);

cleanup:
    if (privdom)
        virObjectUnlock(privdom);
    return ret;
}

static int testDomainSetMetadata(virDomainPtr dom,
                                 int type,
                                 const char *metadata,
                                 const char *key,
                                 const char *uri,
                                 unsigned int flags)
{
    testConnPtr privconn = dom->conn->privateData;
    virDomainObjPtr privdom;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

    testDriverLock(privconn);
    privdom = virDomainObjListFindByName(privconn->domains,
                                         dom->name);
    testDriverUnlock(privconn);

    if (privdom == NULL) {
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
        goto cleanup;
    }

    ret = virDomainObjSetMetadata(privdom, type, metadata, key, uri,
                                  privconn->caps, privconn->xmlopt,
                                  NULL, flags);

cleanup:
    if (privdom)
        virObjectUnlock(privdom);
    return ret;
}


2878 2879 2880
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
                                      int startCell, int maxCells) {
2881
    testConnPtr privconn = conn->privateData;
2882 2883
    int cell;
    size_t i;
2884
    int ret = -1;
2885

2886
    testDriverLock(privconn);
2887
    if (startCell > privconn->numCells) {
2888 2889
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("Range exceeds available cells"));
2890
        goto cleanup;
2891 2892
    }

2893 2894 2895 2896
    for (cell = startCell, i = 0;
         (cell < privconn->numCells && i < maxCells);
         ++cell, ++i) {
        freemems[i] = privconn->cells[cell].mem;
2897
    }
2898
    ret = i;
2899

2900
cleanup:
2901
    testDriverUnlock(privconn);
2902
    return ret;
2903 2904 2905
}


2906
static int testDomainCreateWithFlags(virDomainPtr domain, unsigned int flags) {
2907 2908
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2909
    virDomainEventPtr event = NULL;
2910
    int ret = -1;
2911

2912 2913
    virCheckFlags(0, -1);

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

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

J
Jiri Denemark 已提交
2923
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_SHUTOFF) {
2924 2925
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Domain '%s' is already running"), domain->name);
2926
        goto cleanup;
2927 2928
    }

2929
    if (testDomainStartState(privconn, privdom,
J
Jiri Denemark 已提交
2930
                             VIR_DOMAIN_RUNNING_BOOTED) < 0)
2931 2932 2933
        goto cleanup;
    domain->id = privdom->def->id;

2934 2935 2936
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
2937
    ret = 0;
2938

2939
cleanup:
2940
    if (privdom)
2941
        virObjectUnlock(privdom);
2942 2943
    if (event)
        testDomainEventQueue(privconn, event);
2944
    testDriverUnlock(privconn);
2945
    return ret;
2946 2947
}

2948 2949 2950 2951
static int testDomainCreate(virDomainPtr domain) {
    return testDomainCreateWithFlags(domain, 0);
}

2952 2953 2954
static int testDomainUndefineFlags(virDomainPtr domain,
                                   unsigned int flags)
{
2955 2956
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2957
    virDomainEventPtr event = NULL;
2958
    int nsnapshots;
2959
    int ret = -1;
2960

2961 2962
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
                  VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
2963

2964
    testDriverLock(privconn);
2965 2966
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2967 2968

    if (privdom == NULL) {
2969
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2970
        goto cleanup;
2971
    }
2972

C
Cole Robinson 已提交
2973 2974 2975 2976 2977 2978 2979 2980
    if (privdom->hasManagedSave &&
        !(flags & VIR_DOMAIN_UNDEFINE_MANAGED_SAVE)) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("Refusing to undefine while domain managed "
                         "save image exists"));
        goto cleanup;
    }

2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998
    /* Requiring an inactive VM is part of the documented API for
     * UNDEFINE_SNAPSHOTS_METADATA
     */
    if (!virDomainObjIsActive(privdom) &&
        (nsnapshots = virDomainSnapshotObjListNum(privdom->snapshots,
                                                  NULL, 0))) {
        if (!(flags & VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA)) {
            virReportError(VIR_ERR_OPERATION_INVALID,
                           _("cannot delete inactive domain with %d "
                             "snapshots"),
                           nsnapshots);
            goto cleanup;
        }

        /* There isn't actually anything to do, we are just emulating qemu
         * behavior here. */
    }

2999 3000 3001
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
C
Cole Robinson 已提交
3002 3003
    privdom->hasManagedSave = false;

3004 3005
    if (virDomainObjIsActive(privdom)) {
        privdom->persistent = 0;
3006
    } else {
3007 3008
        virDomainObjListRemove(privconn->domains,
                               privdom);
3009 3010 3011
        privdom = NULL;
    }

3012
    ret = 0;
3013

3014
cleanup:
3015
    if (privdom)
3016
        virObjectUnlock(privdom);
3017 3018
    if (event)
        testDomainEventQueue(privconn, event);
3019
    testDriverUnlock(privconn);
3020
    return ret;
3021 3022
}

3023 3024 3025 3026 3027
static int testDomainUndefine(virDomainPtr domain)
{
    return testDomainUndefineFlags(domain, 0);
}

3028 3029 3030
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
3031 3032
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
3033
    int ret = -1;
3034

3035
    testDriverLock(privconn);
3036 3037
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
3038
    testDriverUnlock(privconn);
3039 3040

    if (privdom == NULL) {
3041
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3042
        goto cleanup;
3043 3044
    }

3045
    *autostart = privdom->autostart;
3046 3047 3048
    ret = 0;

cleanup:
3049
    if (privdom)
3050
        virObjectUnlock(privdom);
3051
    return ret;
3052 3053 3054 3055 3056 3057
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
3058 3059
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
3060
    int ret = -1;
3061

3062
    testDriverLock(privconn);
3063 3064
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
3065
    testDriverUnlock(privconn);
3066 3067

    if (privdom == NULL) {
3068
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3069
        goto cleanup;
3070 3071
    }

3072
    privdom->autostart = autostart ? 1 : 0;
3073 3074 3075
    ret = 0;

cleanup:
3076
    if (privdom)
3077
        virObjectUnlock(privdom);
3078
    return ret;
3079
}
3080

3081
static char *testDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED,
3082 3083
                                        int *nparams)
{
3084 3085
    char *type = NULL;

3086 3087 3088
    if (nparams)
        *nparams = 1;

3089
    ignore_value(VIR_STRDUP(type, "fair"));
3090

3091 3092 3093
    return type;
}

3094
static int
3095 3096 3097 3098
testDomainGetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int *nparams,
                                      unsigned int flags)
3099
{
3100 3101
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
3102
    int ret = -1;
3103

3104 3105
    virCheckFlags(0, -1);

3106
    testDriverLock(privconn);
3107 3108
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
3109
    testDriverUnlock(privconn);
3110 3111

    if (privdom == NULL) {
3112
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3113
        goto cleanup;
3114 3115
    }

3116 3117
    if (virTypedParameterAssign(params, VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, 50) < 0)
3118
        goto cleanup;
3119 3120
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
3121 3122

    *nparams = 1;
3123 3124 3125
    ret = 0;

cleanup:
3126
    if (privdom)
3127
        virObjectUnlock(privdom);
3128
    return ret;
3129
}
3130

3131
static int
3132 3133 3134
testDomainGetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int *nparams)
3135
{
3136
    return testDomainGetSchedulerParametersFlags(domain, params, nparams, 0);
3137
}
3138

3139
static int
3140 3141 3142 3143
testDomainSetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int nparams,
                                      unsigned int flags)
3144
{
3145 3146
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
3147 3148
    int ret = -1;
    size_t i;
3149

3150
    virCheckFlags(0, -1);
3151 3152 3153 3154
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
3155
        return -1;
3156

3157
    testDriverLock(privconn);
3158 3159
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
3160
    testDriverUnlock(privconn);
3161 3162

    if (privdom == NULL) {
3163
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3164
        goto cleanup;
3165 3166
    }

3167
    for (i = 0; i < nparams; i++) {
3168 3169 3170
        if (STREQ(params[i].field, VIR_DOMAIN_SCHEDULER_WEIGHT)) {
            /* XXX */
            /*privdom->weight = params[i].value.ui;*/
3171
        }
3172
    }
3173

3174 3175 3176
    ret = 0;

cleanup:
3177
    if (privdom)
3178
        virObjectUnlock(privdom);
3179
    return ret;
3180 3181
}

3182
static int
3183 3184 3185
testDomainSetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int nparams)
3186
{
3187
    return testDomainSetSchedulerParametersFlags(domain, params, nparams, 0);
3188 3189
}

3190 3191 3192 3193 3194 3195 3196 3197
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;
3198
    int ret = -1;
3199 3200

    testDriverLock(privconn);
3201 3202
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
3203 3204 3205
    testDriverUnlock(privconn);

    if (privdom == NULL) {
3206
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3207 3208 3209
        goto error;
    }

3210
    if (virDomainDiskIndexByName(privdom->def, path, false) < 0) {
3211 3212
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path: %s"), path);
3213 3214 3215 3216
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
3217
        virReportSystemError(errno,
3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232
                             "%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)
3233
        virObjectUnlock(privdom);
3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244
    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;
3245 3246
    size_t i;
    int found = 0, ret = -1;
3247 3248

    testDriverLock(privconn);
3249 3250
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
3251 3252 3253
    testDriverUnlock(privconn);

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

3258
    for (i = 0; i < privdom->def->nnets; i++) {
3259
        if (privdom->def->nets[i]->ifname &&
3260
            STREQ(privdom->def->nets[i]->ifname, path)) {
3261 3262 3263 3264 3265 3266
            found = 1;
            break;
        }
    }

    if (!found) {
3267 3268
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path, '%s' is not a known interface"), path);
3269 3270 3271 3272
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
3273
        virReportSystemError(errno,
3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291
                             "%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)
3292
        virObjectUnlock(privdom);
3293 3294 3295
    return ret;
}

3296
static virDrvOpenStatus testNetworkOpen(virConnectPtr conn,
3297
                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
3298 3299 3300 3301
                                        unsigned int flags)
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

3302 3303 3304 3305 3306 3307 3308
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

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

3309
static int testNetworkClose(virConnectPtr conn) {
3310 3311 3312 3313 3314
    conn->networkPrivateData = NULL;
    return 0;
}


3315 3316
static virNetworkPtr testNetworkLookupByUUID(virConnectPtr conn,
                                             const unsigned char *uuid)
3317
{
3318 3319
    testConnPtr privconn = conn->privateData;
    virNetworkObjPtr net;
3320
    virNetworkPtr ret = NULL;
3321

3322 3323 3324 3325 3326
    testDriverLock(privconn);
    net = virNetworkFindByUUID(&privconn->networks, uuid);
    testDriverUnlock(privconn);

    if (net == NULL) {
3327
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3328
        goto cleanup;
3329 3330
    }

3331 3332 3333
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

cleanup:
3334 3335
    if (net)
        virNetworkObjUnlock(net);
3336
    return ret;
3337
}
3338

3339
static virNetworkPtr testNetworkLookupByName(virConnectPtr conn,
3340
                                             const char *name)
3341
{
3342
    testConnPtr privconn = conn->privateData;
3343 3344
    virNetworkObjPtr net;
    virNetworkPtr ret = NULL;
3345

3346 3347 3348 3349 3350
    testDriverLock(privconn);
    net = virNetworkFindByName(&privconn->networks, name);
    testDriverUnlock(privconn);

    if (net == NULL) {
3351
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3352
        goto cleanup;
3353 3354
    }

3355 3356 3357
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

cleanup:
3358 3359
    if (net)
        virNetworkObjUnlock(net);
3360
    return ret;
3361 3362 3363
}


3364
static int testConnectNumOfNetworks(virConnectPtr conn) {
3365
    testConnPtr privconn = conn->privateData;
3366 3367
    int numActive = 0;
    size_t i;
3368

3369
    testDriverLock(privconn);
3370
    for (i = 0; i < privconn->networks.count; i++) {
3371
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
3372
        if (virNetworkObjIsActive(privconn->networks.objs[i]))
3373
            numActive++;
3374 3375 3376
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
3377

3378
    return numActive;
3379 3380
}

3381
static int testConnectListNetworks(virConnectPtr conn, char **const names, int nnames) {
3382
    testConnPtr privconn = conn->privateData;
3383 3384
    int n = 0;
    size_t i;
3385

3386
    testDriverLock(privconn);
3387
    memset(names, 0, sizeof(*names)*nnames);
3388
    for (i = 0; i < privconn->networks.count && n < nnames; i++) {
3389
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
3390
        if (virNetworkObjIsActive(privconn->networks.objs[i]) &&
3391
            VIR_STRDUP(names[n++], privconn->networks.objs[i]->def->name) < 0) {
3392
            virNetworkObjUnlock(privconn->networks.objs[i]);
3393
            goto error;
3394 3395 3396 3397
        }
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
3398

3399 3400
    return n;

3401
error:
3402
    for (n = 0; n < nnames; n++)
3403
        VIR_FREE(names[n]);
3404
    testDriverUnlock(privconn);
3405
    return -1;
3406 3407
}

3408
static int testConnectNumOfDefinedNetworks(virConnectPtr conn) {
3409
    testConnPtr privconn = conn->privateData;
3410 3411
    int numInactive = 0;
    size_t i;
3412

3413
    testDriverLock(privconn);
3414
    for (i = 0; i < privconn->networks.count; i++) {
3415
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
3416
        if (!virNetworkObjIsActive(privconn->networks.objs[i]))
3417
            numInactive++;
3418 3419 3420
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
3421

3422
    return numInactive;
3423 3424
}

3425
static int testConnectListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
3426
    testConnPtr privconn = conn->privateData;
3427 3428
    int n = 0;
    size_t i;
3429

3430
    testDriverLock(privconn);
3431
    memset(names, 0, sizeof(*names)*nnames);
3432
    for (i = 0; i < privconn->networks.count && n < nnames; i++) {
3433
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
3434
        if (!virNetworkObjIsActive(privconn->networks.objs[i]) &&
3435
            VIR_STRDUP(names[n++], privconn->networks.objs[i]->def->name) < 0) {
3436
            virNetworkObjUnlock(privconn->networks.objs[i]);
3437
            goto error;
3438 3439 3440 3441
        }
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
3442

3443 3444
    return n;

3445
error:
3446
    for (n = 0; n < nnames; n++)
3447
        VIR_FREE(names[n]);
3448
    testDriverUnlock(privconn);
3449
    return -1;
3450 3451
}

3452
static int
3453
testConnectListAllNetworks(virConnectPtr conn,
3454 3455 3456 3457 3458 3459 3460 3461 3462
                           virNetworkPtr **nets,
                           unsigned int flags)
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

    testDriverLock(privconn);
3463
    ret = virNetworkObjListExport(conn, privconn->networks, nets, NULL, flags);
3464 3465 3466 3467
    testDriverUnlock(privconn);

    return ret;
}
3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478

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) {
3479
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499
        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) {
3500
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511
        goto cleanup;
    }
    ret = obj->persistent;

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


3512
static virNetworkPtr testNetworkCreateXML(virConnectPtr conn, const char *xml) {
3513
    testConnPtr privconn = conn->privateData;
3514
    virNetworkDefPtr def;
3515
    virNetworkObjPtr net = NULL;
3516
    virNetworkPtr ret = NULL;
3517

3518
    testDriverLock(privconn);
3519
    if ((def = virNetworkDefParseString(xml)) == NULL)
3520
        goto cleanup;
3521

3522
    if (!(net = virNetworkAssignDef(&privconn->networks, def, false)))
3523 3524
        goto cleanup;
    def = NULL;
3525
    net->active = 1;
3526

3527
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3528

3529 3530
cleanup:
    virNetworkDefFree(def);
3531 3532 3533
    if (net)
        virNetworkObjUnlock(net);
    testDriverUnlock(privconn);
3534
    return ret;
3535 3536
}

3537
static
3538
virNetworkPtr testNetworkDefineXML(virConnectPtr conn, const char *xml)
3539
{
3540
    testConnPtr privconn = conn->privateData;
3541
    virNetworkDefPtr def;
3542
    virNetworkObjPtr net = NULL;
3543
    virNetworkPtr ret = NULL;
3544

3545
    testDriverLock(privconn);
3546
    if ((def = virNetworkDefParseString(xml)) == NULL)
3547
        goto cleanup;
3548

3549
    if (!(net = virNetworkAssignDef(&privconn->networks, def, false)))
3550 3551
        goto cleanup;
    def = NULL;
3552
    net->persistent = 1;
3553

3554
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3555 3556 3557

cleanup:
    virNetworkDefFree(def);
3558 3559 3560
    if (net)
        virNetworkObjUnlock(net);
    testDriverUnlock(privconn);
3561
    return ret;
3562 3563 3564
}

static int testNetworkUndefine(virNetworkPtr network) {
3565 3566
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3567
    int ret = -1;
3568

3569
    testDriverLock(privconn);
3570 3571 3572 3573
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
3574
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3575
        goto cleanup;
3576
    }
3577

D
Daniel P. Berrange 已提交
3578
    if (virNetworkObjIsActive(privnet)) {
3579 3580
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is still running"), network->name);
3581
        goto cleanup;
3582 3583
    }

3584 3585
    virNetworkRemoveInactive(&privconn->networks,
                             privnet);
3586
    privnet = NULL;
3587
    ret = 0;
3588

3589
cleanup:
3590 3591 3592
    if (privnet)
        virNetworkObjUnlock(privnet);
    testDriverUnlock(privconn);
3593
    return ret;
3594 3595
}

3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643
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;
}

3644
static int testNetworkCreate(virNetworkPtr network) {
3645 3646
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3647
    int ret = -1;
3648

3649
    testDriverLock(privconn);
3650 3651
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
3652
    testDriverUnlock(privconn);
3653 3654

    if (privnet == NULL) {
3655
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3656
        goto cleanup;
3657
    }
3658

D
Daniel P. Berrange 已提交
3659
    if (virNetworkObjIsActive(privnet)) {
3660 3661
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is already running"), network->name);
3662
        goto cleanup;
3663 3664
    }

3665
    privnet->active = 1;
3666
    ret = 0;
3667

3668
cleanup:
3669 3670
    if (privnet)
        virNetworkObjUnlock(privnet);
3671
    return ret;
3672 3673 3674
}

static int testNetworkDestroy(virNetworkPtr network) {
3675 3676
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3677
    int ret = -1;
3678

3679
    testDriverLock(privconn);
3680 3681 3682 3683
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
3684
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3685
        goto cleanup;
3686
    }
3687

3688 3689 3690 3691
    privnet->active = 0;
    if (!privnet->persistent) {
        virNetworkRemoveInactive(&privconn->networks,
                                 privnet);
3692
        privnet = NULL;
3693
    }
3694 3695 3696
    ret = 0;

cleanup:
3697 3698 3699
    if (privnet)
        virNetworkObjUnlock(privnet);
    testDriverUnlock(privconn);
3700
    return ret;
3701 3702
}

3703
static char *testNetworkGetXMLDesc(virNetworkPtr network,
E
Eric Blake 已提交
3704
                                   unsigned int flags)
3705
{
3706 3707
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3708
    char *ret = NULL;
3709

E
Eric Blake 已提交
3710 3711
    virCheckFlags(0, NULL);

3712
    testDriverLock(privconn);
3713 3714
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
3715
    testDriverUnlock(privconn);
3716 3717

    if (privnet == NULL) {
3718
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3719
        goto cleanup;
3720
    }
3721

3722
    ret = virNetworkDefFormat(privnet->def, flags);
3723 3724

cleanup:
3725 3726
    if (privnet)
        virNetworkObjUnlock(privnet);
3727
    return ret;
3728 3729 3730
}

static char *testNetworkGetBridgeName(virNetworkPtr network) {
3731
    testConnPtr privconn = network->conn->privateData;
3732
    char *bridge = NULL;
3733 3734
    virNetworkObjPtr privnet;

3735
    testDriverLock(privconn);
3736 3737
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
3738
    testDriverUnlock(privconn);
3739 3740

    if (privnet == NULL) {
3741
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3742
        goto cleanup;
3743 3744
    }

3745
    if (!(privnet->def->bridge)) {
3746 3747 3748
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("network '%s' does not have a bridge name."),
                       privnet->def->name);
3749 3750 3751
        goto cleanup;
    }

3752
    ignore_value(VIR_STRDUP(bridge, privnet->def->bridge));
3753 3754

cleanup:
3755 3756
    if (privnet)
        virNetworkObjUnlock(privnet);
3757 3758 3759 3760 3761
    return bridge;
}

static int testNetworkGetAutostart(virNetworkPtr network,
                                   int *autostart) {
3762 3763
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3764
    int ret = -1;
3765

3766
    testDriverLock(privconn);
3767 3768
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
3769
    testDriverUnlock(privconn);
3770 3771

    if (privnet == NULL) {
3772
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3773
        goto cleanup;
3774 3775
    }

3776
    *autostart = privnet->autostart;
3777 3778 3779
    ret = 0;

cleanup:
3780 3781
    if (privnet)
        virNetworkObjUnlock(privnet);
3782
    return ret;
3783 3784 3785 3786
}

static int testNetworkSetAutostart(virNetworkPtr network,
                                   int autostart) {
3787 3788
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3789
    int ret = -1;
3790

3791
    testDriverLock(privconn);
3792 3793
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
3794
    testDriverUnlock(privconn);
3795 3796

    if (privnet == NULL) {
3797
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3798
        goto cleanup;
3799 3800
    }

3801
    privnet->autostart = autostart ? 1 : 0;
3802 3803 3804
    ret = 0;

cleanup:
3805 3806
    if (privnet)
        virNetworkObjUnlock(privnet);
3807
    return ret;
3808
}
3809

C
Cole Robinson 已提交
3810

L
Laine Stump 已提交
3811 3812 3813 3814
/*
 * Physical host interface routines
 */

3815
static virDrvOpenStatus testInterfaceOpen(virConnectPtr conn,
L
Laine Stump 已提交
3816
                                          virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
3817
                                          unsigned int flags)
L
Laine Stump 已提交
3818
{
E
Eric Blake 已提交
3819 3820
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

L
Laine Stump 已提交
3821 3822 3823 3824 3825 3826 3827
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

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

3828
static int testInterfaceClose(virConnectPtr conn)
L
Laine Stump 已提交
3829 3830 3831 3832 3833 3834
{
    conn->interfacePrivateData = NULL;
    return 0;
}


3835
static int testConnectNumOfInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3836 3837
{
    testConnPtr privconn = conn->privateData;
3838 3839
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3840 3841

    testDriverLock(privconn);
3842
    for (i = 0; (i < privconn->ifaces.count); i++) {
L
Laine Stump 已提交
3843
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3844
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
L
Laine Stump 已提交
3845 3846 3847 3848 3849 3850 3851 3852
            count++;
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3853
static int testConnectListInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3854 3855
{
    testConnPtr privconn = conn->privateData;
3856 3857
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3858 3859 3860

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
3861
    for (i = 0; (i < privconn->ifaces.count) && (n < nnames); i++) {
L
Laine Stump 已提交
3862
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3863
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
3864
            if (VIR_STRDUP(names[n++], privconn->ifaces.objs[i]->def->name) < 0) {
L
Laine Stump 已提交
3865
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
3866
                goto error;
L
Laine Stump 已提交
3867 3868 3869 3870 3871 3872 3873 3874
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

3875
error:
3876
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3877 3878 3879 3880 3881
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

3882
static int testConnectNumOfDefinedInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3883 3884
{
    testConnPtr privconn = conn->privateData;
3885 3886
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3887 3888

    testDriverLock(privconn);
3889
    for (i = 0; i < privconn->ifaces.count; i++) {
L
Laine Stump 已提交
3890
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3891
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
L
Laine Stump 已提交
3892 3893 3894 3895 3896 3897 3898 3899
            count++;
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3900
static int testConnectListDefinedInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3901 3902
{
    testConnPtr privconn = conn->privateData;
3903 3904
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3905 3906 3907

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
3908
    for (i = 0; (i < privconn->ifaces.count) && (n < nnames); i++) {
L
Laine Stump 已提交
3909
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3910
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
3911
            if (VIR_STRDUP(names[n++], privconn->ifaces.objs[i]->def->name) < 0) {
L
Laine Stump 已提交
3912
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
3913
                goto error;
L
Laine Stump 已提交
3914 3915 3916 3917 3918 3919 3920 3921
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

3922
error:
3923
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3924 3925 3926 3927 3928
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

3929
static virInterfacePtr testInterfaceLookupByName(virConnectPtr conn,
L
Laine Stump 已提交
3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940
                                                 const char *name)
{
    testConnPtr privconn = conn->privateData;
    virInterfaceObjPtr iface;
    virInterfacePtr ret = NULL;

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

    if (iface == NULL) {
3941
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952
        goto cleanup;
    }

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

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

3953
static virInterfacePtr testInterfaceLookupByMACString(virConnectPtr conn,
L
Laine Stump 已提交
3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965
                                                      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) {
3966
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3967 3968 3969 3970
        goto cleanup;
    }

    if (ifacect > 1) {
3971
        virReportError(VIR_ERR_MULTIPLE_INTERFACES, NULL);
L
Laine Stump 已提交
3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982
        goto cleanup;
    }

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

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

3983 3984 3985 3986 3987 3988 3989 3990 3991 3992
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) {
3993
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
3994 3995 3996 3997 3998 3999 4000 4001 4002 4003
        goto cleanup;
    }
    ret = virInterfaceObjIsActive(obj);

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

4004
static int testInterfaceChangeBegin(virConnectPtr conn,
E
Eric Blake 已提交
4005
                                    unsigned int flags)
4006 4007 4008 4009
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

E
Eric Blake 已提交
4010 4011
    virCheckFlags(0, -1);

4012 4013
    testDriverLock(privconn);
    if (privconn->transaction_running) {
4014
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
4015
                       _("there is another transaction running."));
4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031
        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 已提交
4032
                                     unsigned int flags)
4033 4034 4035 4036
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

E
Eric Blake 已提交
4037 4038
    virCheckFlags(0, -1);

4039 4040 4041
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
4042
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
4043 4044
                       _("no transaction running, "
                         "nothing to be committed."));
4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059
        goto cleanup;
    }

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

    ret = 0;

cleanup:
    testDriverUnlock(privconn);

    return ret;
}

static int testInterfaceChangeRollback(virConnectPtr conn,
E
Eric Blake 已提交
4060
                                       unsigned int flags)
4061 4062 4063 4064
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

E
Eric Blake 已提交
4065 4066
    virCheckFlags(0, -1);

4067 4068 4069
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
4070
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
4071 4072
                       _("no transaction running, "
                         "nothing to rollback."));
4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089
        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;
}
4090

L
Laine Stump 已提交
4091
static char *testInterfaceGetXMLDesc(virInterfacePtr iface,
E
Eric Blake 已提交
4092
                                     unsigned int flags)
L
Laine Stump 已提交
4093 4094 4095 4096 4097
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr privinterface;
    char *ret = NULL;

E
Eric Blake 已提交
4098 4099
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
4100 4101 4102 4103 4104 4105
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);
    testDriverUnlock(privconn);

    if (privinterface == NULL) {
4106
        virReportError(VIR_ERR_NO_INTERFACE, __FUNCTION__);
L
Laine Stump 已提交
4107 4108 4109
        goto cleanup;
    }

4110
    ret = virInterfaceDefFormat(privinterface->def);
L
Laine Stump 已提交
4111 4112 4113 4114 4115 4116 4117 4118 4119

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


static virInterfacePtr testInterfaceDefineXML(virConnectPtr conn, const char *xmlStr,
E
Eric Blake 已提交
4120
                                              unsigned int flags)
L
Laine Stump 已提交
4121 4122 4123 4124 4125 4126
{
    testConnPtr privconn = conn->privateData;
    virInterfaceDefPtr def;
    virInterfaceObjPtr iface = NULL;
    virInterfacePtr ret = NULL;

E
Eric Blake 已提交
4127 4128
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
4129
    testDriverLock(privconn);
4130
    if ((def = virInterfaceDefParseString(xmlStr)) == NULL)
L
Laine Stump 已提交
4131 4132
        goto cleanup;

4133
    if ((iface = virInterfaceAssignDef(&privconn->ifaces, def)) == NULL)
L
Laine Stump 已提交
4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157
        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) {
4158
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171
        goto cleanup;
    }

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

cleanup:
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceCreate(virInterfacePtr iface,
E
Eric Blake 已提交
4172
                               unsigned int flags)
L
Laine Stump 已提交
4173 4174 4175 4176 4177
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr privinterface;
    int ret = -1;

E
Eric Blake 已提交
4178 4179
    virCheckFlags(0, -1);

L
Laine Stump 已提交
4180 4181 4182 4183 4184
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);

    if (privinterface == NULL) {
4185
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
4186 4187 4188 4189
        goto cleanup;
    }

    if (privinterface->active != 0) {
4190
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204
        goto cleanup;
    }

    privinterface->active = 1;
    ret = 0;

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

static int testInterfaceDestroy(virInterfacePtr iface,
E
Eric Blake 已提交
4205
                                unsigned int flags)
L
Laine Stump 已提交
4206 4207 4208 4209 4210
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr privinterface;
    int ret = -1;

E
Eric Blake 已提交
4211 4212
    virCheckFlags(0, -1);

L
Laine Stump 已提交
4213 4214 4215 4216 4217
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);

    if (privinterface == NULL) {
4218
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
4219 4220 4221 4222
        goto cleanup;
    }

    if (privinterface->active == 0) {
4223
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238
        goto cleanup;
    }

    privinterface->active = 0;
    ret = 0;

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



C
Cole Robinson 已提交
4239 4240 4241 4242
/*
 * Storage Driver routines
 */

4243

4244
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool) {
C
Cole Robinson 已提交
4245 4246 4247 4248 4249

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

4250
    return VIR_STRDUP(pool->configFile, "");
C
Cole Robinson 已提交
4251 4252
}

4253 4254
static virDrvOpenStatus testStorageOpen(virConnectPtr conn,
                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
4255 4256 4257 4258
                                        unsigned int flags)
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270
    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;
}

4271

C
Cole Robinson 已提交
4272 4273 4274
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
                            const unsigned char *uuid) {
4275
    testConnPtr privconn = conn->privateData;
4276 4277
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4278

4279
    testDriverLock(privconn);
4280
    pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid);
4281
    testDriverUnlock(privconn);
4282 4283

    if (pool == NULL) {
4284
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4285
        goto cleanup;
C
Cole Robinson 已提交
4286 4287
    }

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

cleanup:
4292 4293
    if (pool)
        virStoragePoolObjUnlock(pool);
4294
    return ret;
C
Cole Robinson 已提交
4295 4296 4297 4298 4299
}

static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
                            const char *name) {
4300
    testConnPtr privconn = conn->privateData;
4301 4302
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4303

4304
    testDriverLock(privconn);
4305
    pool = virStoragePoolObjFindByName(&privconn->pools, name);
4306
    testDriverUnlock(privconn);
4307 4308

    if (pool == NULL) {
4309
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4310
        goto cleanup;
C
Cole Robinson 已提交
4311 4312
    }

4313 4314
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4315 4316

cleanup:
4317 4318
    if (pool)
        virStoragePoolObjUnlock(pool);
4319
    return ret;
C
Cole Robinson 已提交
4320 4321 4322 4323 4324 4325 4326 4327
}

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

static int
4328
testConnectNumOfStoragePools(virConnectPtr conn) {
4329
    testConnPtr privconn = conn->privateData;
4330 4331
    int numActive = 0;
    size_t i;
C
Cole Robinson 已提交
4332

4333
    testDriverLock(privconn);
4334
    for (i = 0; i < privconn->pools.count; i++)
C
Cole Robinson 已提交
4335 4336
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numActive++;
4337
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4338 4339 4340 4341 4342

    return numActive;
}

static int
4343 4344 4345
testConnectListStoragePools(virConnectPtr conn,
                            char **const names,
                            int nnames) {
4346
    testConnPtr privconn = conn->privateData;
4347 4348
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
4349

4350
    testDriverLock(privconn);
C
Cole Robinson 已提交
4351
    memset(names, 0, sizeof(*names)*nnames);
4352
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
4353
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4354
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
4355
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
4356
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
4357
            goto error;
4358 4359 4360 4361
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4362 4363 4364

    return n;

4365
error:
4366
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
4367
        VIR_FREE(names[n]);
4368
    testDriverUnlock(privconn);
4369
    return -1;
C
Cole Robinson 已提交
4370 4371 4372
}

static int
4373
testConnectNumOfDefinedStoragePools(virConnectPtr conn) {
4374
    testConnPtr privconn = conn->privateData;
4375 4376
    int numInactive = 0;
    size_t i;
C
Cole Robinson 已提交
4377

4378
    testDriverLock(privconn);
4379
    for (i = 0; i < privconn->pools.count; i++) {
4380
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4381 4382
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numInactive++;
4383 4384 4385
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4386 4387 4388 4389 4390

    return numInactive;
}

static int
4391 4392 4393
testConnectListDefinedStoragePools(virConnectPtr conn,
                                   char **const names,
                                   int nnames) {
4394
    testConnPtr privconn = conn->privateData;
4395 4396
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
4397

4398
    testDriverLock(privconn);
C
Cole Robinson 已提交
4399
    memset(names, 0, sizeof(*names)*nnames);
4400
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
4401
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4402
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
4403
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
4404
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
4405
            goto error;
4406 4407 4408 4409
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4410 4411 4412

    return n;

4413
error:
4414
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
4415
        VIR_FREE(names[n]);
4416
    testDriverUnlock(privconn);
4417
    return -1;
C
Cole Robinson 已提交
4418 4419
}

4420
static int
4421 4422 4423
testConnectListAllStoragePools(virConnectPtr conn,
                               virStoragePoolPtr **pools,
                               unsigned int flags)
4424 4425 4426 4427 4428 4429 4430
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

    testDriverLock(privconn);
4431 4432
    ret = virStoragePoolObjListExport(conn, privconn->pools, pools,
                                      NULL, flags);
4433 4434 4435 4436
    testDriverUnlock(privconn);

    return ret;
}
C
Cole Robinson 已提交
4437

4438 4439 4440 4441 4442 4443 4444 4445 4446 4447
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) {
4448
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468
        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) {
4469
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481
        goto cleanup;
    }
    ret = obj->configFile ? 1 : 0;

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



C
Cole Robinson 已提交
4482
static int
4483 4484
testStoragePoolCreate(virStoragePoolPtr pool,
                      unsigned int flags)
E
Eric Blake 已提交
4485
{
4486 4487
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4488
    int ret = -1;
4489

E
Eric Blake 已提交
4490 4491
    virCheckFlags(0, -1);

4492
    testDriverLock(privconn);
4493 4494
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4495
    testDriverUnlock(privconn);
4496 4497

    if (privpool == NULL) {
4498
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4499
        goto cleanup;
4500 4501
    }

4502
    if (virStoragePoolObjIsActive(privpool)) {
4503 4504
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4505 4506
        goto cleanup;
    }
C
Cole Robinson 已提交
4507 4508

    privpool->active = 1;
4509
    ret = 0;
C
Cole Robinson 已提交
4510

4511
cleanup:
4512 4513
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4514
    return ret;
C
Cole Robinson 已提交
4515 4516 4517
}

static char *
4518 4519 4520 4521
testConnectFindStoragePoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type,
                                  const char *srcSpec,
                                  unsigned int flags)
C
Cole Robinson 已提交
4522
{
4523 4524 4525 4526
    virStoragePoolSourcePtr source = NULL;
    int pool_type;
    char *ret = NULL;

E
Eric Blake 已提交
4527 4528
    virCheckFlags(0, NULL);

4529 4530
    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
4531 4532
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
4533 4534 4535 4536
        goto cleanup;
    }

    if (srcSpec) {
4537
        source = virStoragePoolDefParseSourceString(srcSpec, pool_type);
4538 4539 4540 4541 4542 4543 4544
        if (!source)
            goto cleanup;
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
4545
        ignore_value(VIR_STRDUP(ret, defaultPoolSourcesLogicalXML));
4546 4547 4548
        break;

    case VIR_STORAGE_POOL_NETFS:
4549
        if (!source || !source->hosts[0].name) {
4550 4551
            virReportError(VIR_ERR_INVALID_ARG,
                           "%s", _("hostname must be specified for netfs sources"));
4552 4553 4554
            goto cleanup;
        }

4555 4556
        ignore_value(virAsprintf(&ret, defaultPoolSourcesNetFSXML,
                                 source->hosts[0].name));
4557 4558 4559
        break;

    default:
4560 4561
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source discovery"), type);
4562 4563 4564 4565 4566
    }

cleanup:
    virStoragePoolSourceFree(source);
    return ret;
C
Cole Robinson 已提交
4567 4568 4569 4570
}


static virStoragePoolPtr
4571 4572 4573
testStoragePoolCreateXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4574
{
4575
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4576
    virStoragePoolDefPtr def;
4577
    virStoragePoolObjPtr pool = NULL;
4578
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4579

E
Eric Blake 已提交
4580 4581
    virCheckFlags(0, NULL);

4582
    testDriverLock(privconn);
4583
    if (!(def = virStoragePoolDefParseString(xml)))
4584
        goto cleanup;
C
Cole Robinson 已提交
4585

4586 4587 4588 4589
    pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid);
    if (!pool)
        pool = virStoragePoolObjFindByName(&privconn->pools, def->name);
    if (pool) {
4590 4591
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("storage pool already exists"));
4592
        goto cleanup;
C
Cole Robinson 已提交
4593 4594
    }

4595
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4596
        goto cleanup;
4597
    def = NULL;
C
Cole Robinson 已提交
4598

4599
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4600
        virStoragePoolObjRemove(&privconn->pools, pool);
4601 4602
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4603 4604 4605
    }
    pool->active = 1;

4606 4607
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4608 4609 4610

cleanup:
    virStoragePoolDefFree(def);
4611 4612 4613
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4614
    return ret;
C
Cole Robinson 已提交
4615 4616 4617
}

static virStoragePoolPtr
4618 4619 4620
testStoragePoolDefineXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4621
{
4622
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4623
    virStoragePoolDefPtr def;
4624
    virStoragePoolObjPtr pool = NULL;
4625
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4626

E
Eric Blake 已提交
4627 4628
    virCheckFlags(0, NULL);

4629
    testDriverLock(privconn);
4630
    if (!(def = virStoragePoolDefParseString(xml)))
4631
        goto cleanup;
C
Cole Robinson 已提交
4632 4633 4634 4635 4636

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

4637
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4638 4639
        goto cleanup;
    def = NULL;
C
Cole Robinson 已提交
4640

4641
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4642
        virStoragePoolObjRemove(&privconn->pools, pool);
4643 4644
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4645 4646
    }

4647 4648
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4649 4650 4651

cleanup:
    virStoragePoolDefFree(def);
4652 4653 4654
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4655
    return ret;
C
Cole Robinson 已提交
4656 4657 4658
}

static int
4659 4660 4661
testStoragePoolUndefine(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4662
    int ret = -1;
4663

4664
    testDriverLock(privconn);
4665 4666 4667 4668
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
4669
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4670
        goto cleanup;
4671 4672
    }

4673
    if (virStoragePoolObjIsActive(privpool)) {
4674 4675
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4676 4677
        goto cleanup;
    }
C
Cole Robinson 已提交
4678 4679

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

4682
cleanup:
4683 4684 4685
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
4686
    return ret;
C
Cole Robinson 已提交
4687 4688 4689
}

static int
4690
testStoragePoolBuild(virStoragePoolPtr pool,
E
Eric Blake 已提交
4691 4692
                     unsigned int flags)
{
4693 4694
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4695
    int ret = -1;
4696

E
Eric Blake 已提交
4697 4698
    virCheckFlags(0, -1);

4699
    testDriverLock(privconn);
4700 4701
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4702
    testDriverUnlock(privconn);
4703 4704

    if (privpool == NULL) {
4705
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4706
        goto cleanup;
4707 4708
    }

4709
    if (virStoragePoolObjIsActive(privpool)) {
4710 4711
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4712 4713
        goto cleanup;
    }
4714
    ret = 0;
C
Cole Robinson 已提交
4715

4716
cleanup:
4717 4718
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4719
    return ret;
C
Cole Robinson 已提交
4720 4721 4722 4723
}


static int
4724 4725 4726
testStoragePoolDestroy(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4727
    int ret = -1;
4728

4729
    testDriverLock(privconn);
4730 4731 4732 4733
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
4734
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4735
        goto cleanup;
4736 4737 4738
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4739 4740
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4741
        goto cleanup;
4742
    }
C
Cole Robinson 已提交
4743 4744 4745

    privpool->active = 0;

4746
    if (privpool->configFile == NULL) {
C
Cole Robinson 已提交
4747
        virStoragePoolObjRemove(&privconn->pools, privpool);
4748 4749
        privpool = NULL;
    }
4750
    ret = 0;
C
Cole Robinson 已提交
4751

4752
cleanup:
4753 4754 4755
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
4756
    return ret;
C
Cole Robinson 已提交
4757 4758 4759 4760
}


static int
4761
testStoragePoolDelete(virStoragePoolPtr pool,
E
Eric Blake 已提交
4762 4763
                      unsigned int flags)
{
4764 4765
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4766
    int ret = -1;
4767

E
Eric Blake 已提交
4768 4769
    virCheckFlags(0, -1);

4770
    testDriverLock(privconn);
4771 4772
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4773
    testDriverUnlock(privconn);
4774 4775

    if (privpool == NULL) {
4776
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4777 4778 4779 4780
        goto cleanup;
    }

    if (virStoragePoolObjIsActive(privpool)) {
4781 4782
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4783
        goto cleanup;
4784 4785
    }

4786
    ret = 0;
C
Cole Robinson 已提交
4787

4788
cleanup:
4789 4790
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4791
    return ret;
C
Cole Robinson 已提交
4792 4793 4794 4795
}


static int
4796
testStoragePoolRefresh(virStoragePoolPtr pool,
E
Eric Blake 已提交
4797 4798
                       unsigned int flags)
{
4799 4800
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4801
    int ret = -1;
4802

E
Eric Blake 已提交
4803 4804
    virCheckFlags(0, -1);

4805
    testDriverLock(privconn);
4806 4807
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4808
    testDriverUnlock(privconn);
4809 4810

    if (privpool == NULL) {
4811
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4812
        goto cleanup;
4813 4814 4815
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4816 4817
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4818
        goto cleanup;
4819
    }
4820
    ret = 0;
C
Cole Robinson 已提交
4821

4822
cleanup:
4823 4824
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4825
    return ret;
C
Cole Robinson 已提交
4826 4827 4828 4829
}


static int
4830
testStoragePoolGetInfo(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4831
                       virStoragePoolInfoPtr info) {
4832 4833
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4834
    int ret = -1;
4835

4836
    testDriverLock(privconn);
4837 4838
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4839
    testDriverUnlock(privconn);
4840 4841

    if (privpool == NULL) {
4842
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4843
        goto cleanup;
4844
    }
C
Cole Robinson 已提交
4845 4846 4847 4848 4849 4850 4851 4852 4853

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

4856
cleanup:
4857 4858
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4859
    return ret;
C
Cole Robinson 已提交
4860 4861 4862
}

static char *
4863
testStoragePoolGetXMLDesc(virStoragePoolPtr pool,
E
Eric Blake 已提交
4864 4865
                          unsigned int flags)
{
4866 4867
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4868
    char *ret = NULL;
4869

E
Eric Blake 已提交
4870 4871
    virCheckFlags(0, NULL);

4872
    testDriverLock(privconn);
4873 4874
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4875
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4876

4877
    if (privpool == NULL) {
4878
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4879
        goto cleanup;
4880 4881
    }

4882
    ret = virStoragePoolDefFormat(privpool->def);
4883 4884

cleanup:
4885 4886
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4887
    return ret;
C
Cole Robinson 已提交
4888 4889 4890
}

static int
4891
testStoragePoolGetAutostart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4892
                            int *autostart) {
4893 4894
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4895
    int ret = -1;
4896

4897
    testDriverLock(privconn);
4898 4899
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4900
    testDriverUnlock(privconn);
4901 4902

    if (privpool == NULL) {
4903
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4904
        goto cleanup;
4905
    }
C
Cole Robinson 已提交
4906 4907 4908 4909 4910 4911

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

4914
cleanup:
4915 4916
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4917
    return ret;
C
Cole Robinson 已提交
4918 4919 4920
}

static int
4921
testStoragePoolSetAutostart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4922
                            int autostart) {
4923 4924
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4925
    int ret = -1;
4926

4927
    testDriverLock(privconn);
4928 4929
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4930
    testDriverUnlock(privconn);
4931 4932

    if (privpool == NULL) {
4933
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4934
        goto cleanup;
4935
    }
C
Cole Robinson 已提交
4936 4937

    if (!privpool->configFile) {
4938 4939
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("pool has no config file"));
4940
        goto cleanup;
C
Cole Robinson 已提交
4941 4942 4943 4944
    }

    autostart = (autostart != 0);
    privpool->autostart = autostart;
4945 4946 4947
    ret = 0;

cleanup:
4948 4949
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4950
    return ret;
C
Cole Robinson 已提交
4951 4952 4953 4954
}


static int
4955
testStoragePoolNumOfVolumes(virStoragePoolPtr pool) {
4956 4957
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4958
    int ret = -1;
4959

4960
    testDriverLock(privconn);
4961 4962
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4963
    testDriverUnlock(privconn);
4964 4965

    if (privpool == NULL) {
4966
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4967
        goto cleanup;
4968 4969 4970
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4971 4972
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4973
        goto cleanup;
4974
    }
C
Cole Robinson 已提交
4975

4976 4977 4978
    ret = privpool->volumes.count;

cleanup:
4979 4980
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4981
    return ret;
C
Cole Robinson 已提交
4982 4983 4984
}

static int
4985
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4986 4987
                           char **const names,
                           int maxnames) {
4988 4989
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4990 4991
    size_t i = 0;
    int n = 0;
C
Cole Robinson 已提交
4992

4993
    memset(names, 0, maxnames * sizeof(*names));
4994 4995

    testDriverLock(privconn);
4996 4997
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4998
    testDriverUnlock(privconn);
4999 5000

    if (privpool == NULL) {
5001
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5002
        goto cleanup;
5003 5004 5005 5006
    }


    if (!virStoragePoolObjIsActive(privpool)) {
5007 5008
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
5009
        goto cleanup;
5010 5011
    }

5012
    for (i = 0; i < privpool->volumes.count && n < maxnames; i++) {
5013
        if (VIR_STRDUP(names[n++], privpool->volumes.objs[i]->name) < 0)
C
Cole Robinson 已提交
5014 5015 5016
            goto cleanup;
    }

5017
    virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
5018 5019 5020
    return n;

 cleanup:
5021
    for (n = 0; n < maxnames; n++)
C
Cole Robinson 已提交
5022 5023
        VIR_FREE(names[i]);

5024
    memset(names, 0, maxnames * sizeof(*names));
5025 5026
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
5027 5028 5029
    return -1;
}

5030 5031 5032 5033 5034 5035
static int
testStoragePoolListAllVolumes(virStoragePoolPtr obj,
                              virStorageVolPtr **vols,
                              unsigned int flags) {
    testConnPtr privconn = obj->conn->privateData;
    virStoragePoolObjPtr pool;
5036
    size_t i;
5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065
    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;
    }

5066
    if (VIR_ALLOC_N(tmp_vols, pool->volumes.count + 1) < 0)
5067 5068
         goto cleanup;

5069
    for (i = 0; i < pool->volumes.count; i++) {
5070 5071
        if (!(vol = virGetStorageVol(obj->conn, pool->def->name,
                                     pool->volumes.objs[i]->name,
5072 5073
                                     pool->volumes.objs[i]->key,
                                     NULL, NULL)))
5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087
            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]);
        }
5088
        VIR_FREE(tmp_vols);
5089 5090 5091 5092 5093 5094 5095
    }

    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
C
Cole Robinson 已提交
5096 5097

static virStorageVolPtr
5098 5099
testStorageVolLookupByName(virStoragePoolPtr pool,
                           const char *name ATTRIBUTE_UNUSED) {
5100 5101 5102
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5103
    virStorageVolPtr ret = NULL;
5104

5105
    testDriverLock(privconn);
5106 5107
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
5108
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
5109

5110
    if (privpool == NULL) {
5111
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5112
        goto cleanup;
5113 5114 5115 5116
    }


    if (!virStoragePoolObjIsActive(privpool)) {
5117 5118
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
5119
        goto cleanup;
5120 5121 5122 5123 5124
    }

    privvol = virStorageVolDefFindByName(privpool, name);

    if (!privvol) {
5125 5126
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"), name);
5127
        goto cleanup;
C
Cole Robinson 已提交
5128 5129
    }

5130
    ret = virGetStorageVol(pool->conn, privpool->def->name,
5131 5132
                           privvol->name, privvol->key,
                           NULL, NULL);
5133 5134

cleanup:
5135 5136
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5137
    return ret;
C
Cole Robinson 已提交
5138 5139 5140 5141
}


static virStorageVolPtr
5142 5143
testStorageVolLookupByKey(virConnectPtr conn,
                          const char *key) {
5144
    testConnPtr privconn = conn->privateData;
5145
    size_t i;
5146
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
5147

5148
    testDriverLock(privconn);
5149
    for (i = 0; i < privconn->pools.count; i++) {
5150
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
5151
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
5152
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
5153 5154
                virStorageVolDefFindByKey(privconn->pools.objs[i], key);

5155 5156 5157 5158
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
5159 5160
                                       privvol->key,
                                       NULL, NULL);
5161
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
5162 5163
                break;
            }
C
Cole Robinson 已提交
5164
        }
5165
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
5166
    }
5167
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
5168

5169
    if (!ret)
5170 5171
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching key '%s'"), key);
5172 5173

    return ret;
C
Cole Robinson 已提交
5174 5175 5176
}

static virStorageVolPtr
5177 5178
testStorageVolLookupByPath(virConnectPtr conn,
                           const char *path) {
5179
    testConnPtr privconn = conn->privateData;
5180
    size_t i;
5181
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
5182

5183
    testDriverLock(privconn);
5184
    for (i = 0; i < privconn->pools.count; i++) {
5185
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
5186
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
5187
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
5188 5189
                virStorageVolDefFindByPath(privconn->pools.objs[i], path);

5190 5191 5192 5193
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
5194 5195
                                       privvol->key,
                                       NULL, NULL);
5196
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
5197 5198
                break;
            }
C
Cole Robinson 已提交
5199
        }
5200
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
5201
    }
5202
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
5203

5204
    if (!ret)
5205 5206
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching path '%s'"), path);
5207 5208

    return ret;
C
Cole Robinson 已提交
5209 5210 5211
}

static virStorageVolPtr
5212 5213 5214
testStorageVolCreateXML(virStoragePoolPtr pool,
                        const char *xmldesc,
                        unsigned int flags)
E
Eric Blake 已提交
5215
{
5216 5217
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
5218 5219
    virStorageVolDefPtr privvol = NULL;
    virStorageVolPtr ret = NULL;
5220

E
Eric Blake 已提交
5221 5222
    virCheckFlags(0, NULL);

5223
    testDriverLock(privconn);
5224 5225
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
5226
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
5227

5228
    if (privpool == NULL) {
5229
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5230
        goto cleanup;
5231 5232 5233
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5234 5235
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
5236
        goto cleanup;
5237
    }
C
Cole Robinson 已提交
5238

5239
    privvol = virStorageVolDefParseString(privpool->def, xmldesc);
5240
    if (privvol == NULL)
5241
        goto cleanup;
5242 5243

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
5244 5245
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
5246
        goto cleanup;
C
Cole Robinson 已提交
5247 5248 5249
    }

    /* Make sure enough space */
5250
    if ((privpool->def->allocation + privvol->allocation) >
C
Cole Robinson 已提交
5251
         privpool->def->capacity) {
5252 5253 5254
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
5255
        goto cleanup;
C
Cole Robinson 已提交
5256 5257 5258
    }

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

5262 5263
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
5264
                    privvol->name) == -1)
5265
        goto cleanup;
C
Cole Robinson 已提交
5266

5267
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0)
5268
        goto cleanup;
C
Cole Robinson 已提交
5269

5270
    privpool->def->allocation += privvol->allocation;
C
Cole Robinson 已提交
5271 5272 5273
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

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

5276
    ret = virGetStorageVol(pool->conn, privpool->def->name,
5277 5278
                           privvol->name, privvol->key,
                           NULL, NULL);
5279
    privvol = NULL;
5280 5281 5282

cleanup:
    virStorageVolDefFree(privvol);
5283 5284
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5285
    return ret;
C
Cole Robinson 已提交
5286 5287
}

5288
static virStorageVolPtr
5289 5290 5291 5292
testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
                            const char *xmldesc,
                            virStorageVolPtr clonevol,
                            unsigned int flags)
E
Eric Blake 已提交
5293
{
5294 5295 5296 5297 5298
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol = NULL, origvol = NULL;
    virStorageVolPtr ret = NULL;

E
Eric Blake 已提交
5299 5300
    virCheckFlags(0, NULL);

5301 5302 5303 5304 5305 5306
    testDriverLock(privconn);
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
    testDriverUnlock(privconn);

    if (privpool == NULL) {
5307
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5308 5309 5310 5311
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5312 5313
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
5314 5315 5316
        goto cleanup;
    }

5317
    privvol = virStorageVolDefParseString(privpool->def, xmldesc);
5318 5319 5320 5321
    if (privvol == NULL)
        goto cleanup;

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
5322 5323
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
5324 5325 5326 5327 5328
        goto cleanup;
    }

    origvol = virStorageVolDefFindByName(privpool, clonevol->name);
    if (!origvol) {
5329 5330 5331
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       clonevol->name);
5332 5333 5334 5335 5336 5337
        goto cleanup;
    }

    /* Make sure enough space */
    if ((privpool->def->allocation + privvol->allocation) >
         privpool->def->capacity) {
5338 5339 5340
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
5341 5342 5343 5344 5345 5346
        goto cleanup;
    }
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    if (VIR_REALLOC_N(privpool->volumes.objs,
5347
                      privpool->volumes.count+1) < 0)
5348 5349
        goto cleanup;

5350 5351
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
5352
                    privvol->name) == -1)
5353 5354
        goto cleanup;

5355
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0)
5356 5357 5358 5359 5360 5361 5362 5363 5364
        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,
5365 5366
                           privvol->name, privvol->key,
                           NULL, NULL);
5367 5368 5369 5370 5371 5372 5373 5374 5375
    privvol = NULL;

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

C
Cole Robinson 已提交
5376
static int
5377 5378
testStorageVolDelete(virStorageVolPtr vol,
                     unsigned int flags)
E
Eric Blake 已提交
5379
{
5380 5381 5382
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5383
    size_t i;
5384
    int ret = -1;
C
Cole Robinson 已提交
5385

E
Eric Blake 已提交
5386 5387
    virCheckFlags(0, -1);

5388
    testDriverLock(privconn);
5389 5390
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5391
    testDriverUnlock(privconn);
5392 5393

    if (privpool == NULL) {
5394
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5395
        goto cleanup;
5396 5397 5398 5399 5400 5401
    }


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

    if (privvol == NULL) {
5402 5403 5404
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5405
        goto cleanup;
5406 5407 5408
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5409 5410
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5411
        goto cleanup;
5412 5413 5414
    }


C
Cole Robinson 已提交
5415 5416 5417 5418
    privpool->def->allocation -= privvol->allocation;
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

5419
    for (i = 0; i < privpool->volumes.count; i++) {
C
Cole Robinson 已提交
5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437
        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;
        }
    }
5438
    ret = 0;
C
Cole Robinson 已提交
5439

5440
cleanup:
5441 5442
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5443
    return ret;
C
Cole Robinson 已提交
5444 5445 5446 5447 5448
}


static int testStorageVolumeTypeForPool(int pooltype) {

5449
    switch (pooltype) {
C
Cole Robinson 已提交
5450 5451 5452 5453 5454 5455 5456 5457 5458 5459
        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
5460 5461
testStorageVolGetInfo(virStorageVolPtr vol,
                      virStorageVolInfoPtr info) {
5462 5463 5464
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5465
    int ret = -1;
5466

5467
    testDriverLock(privconn);
5468 5469
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5470
    testDriverUnlock(privconn);
5471 5472

    if (privpool == NULL) {
5473
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5474
        goto cleanup;
5475 5476 5477 5478 5479
    }

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

    if (privvol == NULL) {
5480 5481 5482
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5483
        goto cleanup;
5484 5485 5486
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5487 5488
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5489
        goto cleanup;
5490
    }
C
Cole Robinson 已提交
5491 5492 5493 5494 5495

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

5498
cleanup:
5499 5500
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5501
    return ret;
C
Cole Robinson 已提交
5502 5503 5504
}

static char *
5505 5506
testStorageVolGetXMLDesc(virStorageVolPtr vol,
                         unsigned int flags)
E
Eric Blake 已提交
5507
{
5508 5509 5510
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5511
    char *ret = NULL;
5512

E
Eric Blake 已提交
5513 5514
    virCheckFlags(0, NULL);

5515
    testDriverLock(privconn);
5516 5517
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5518
    testDriverUnlock(privconn);
5519 5520

    if (privpool == NULL) {
5521
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5522
        goto cleanup;
5523 5524 5525 5526 5527
    }

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

    if (privvol == NULL) {
5528 5529 5530
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5531
        goto cleanup;
5532
    }
C
Cole Robinson 已提交
5533

5534
    if (!virStoragePoolObjIsActive(privpool)) {
5535 5536
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5537
        goto cleanup;
5538 5539
    }

5540
    ret = virStorageVolDefFormat(privpool->def, privvol);
5541 5542

cleanup:
5543 5544
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5545
    return ret;
C
Cole Robinson 已提交
5546 5547 5548
}

static char *
5549
testStorageVolGetPath(virStorageVolPtr vol) {
5550 5551 5552
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5553
    char *ret = NULL;
5554

5555
    testDriverLock(privconn);
5556 5557
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5558
    testDriverUnlock(privconn);
5559 5560

    if (privpool == NULL) {
5561
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5562
        goto cleanup;
5563 5564 5565 5566 5567
    }

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

    if (privvol == NULL) {
5568 5569 5570
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5571
        goto cleanup;
5572 5573 5574
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5575 5576
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5577
        goto cleanup;
5578 5579
    }

5580
    ignore_value(VIR_STRDUP(ret, privvol->target.path));
5581 5582

cleanup:
5583 5584
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
5585 5586 5587
    return ret;
}

5588

5589
/* Node device implementations */
5590 5591 5592
static virDrvOpenStatus testNodeDeviceOpen(virConnectPtr conn,
                                           virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                           unsigned int flags)
E
Eric Blake 已提交
5593 5594 5595
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

5596 5597 5598
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

5599
    conn->nodeDevicePrivateData = conn->privateData;
5600 5601 5602
    return VIR_DRV_OPEN_SUCCESS;
}

5603 5604
static int testNodeDeviceClose(virConnectPtr conn) {
    conn->nodeDevicePrivateData = NULL;
5605 5606 5607
    return 0;
}

5608 5609 5610
static int
testNodeNumOfDevices(virConnectPtr conn,
                     const char *cap,
E
Eric Blake 已提交
5611
                     unsigned int flags)
5612 5613 5614
{
    testConnPtr driver = conn->privateData;
    int ndevs = 0;
5615
    size_t i;
5616

E
Eric Blake 已提交
5617 5618
    virCheckFlags(0, -1);

5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633
    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 已提交
5634
                    unsigned int flags)
5635 5636 5637
{
    testConnPtr driver = conn->privateData;
    int ndevs = 0;
5638
    size_t i;
5639

E
Eric Blake 已提交
5640 5641
    virCheckFlags(0, -1);

5642 5643 5644 5645 5646
    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)) {
5647
            if (VIR_STRDUP(names[ndevs++], driver->devs.objs[i]->def->name) < 0) {
5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677
                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) {
5678
        virReportError(VIR_ERR_NO_NODE_DEVICE, NULL);
5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690
        goto cleanup;
    }

    ret = virGetNodeDevice(conn, name);

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

static char *
5691
testNodeDeviceGetXMLDesc(virNodeDevicePtr dev,
E
Eric Blake 已提交
5692
                         unsigned int flags)
5693 5694 5695 5696 5697
{
    testConnPtr driver = dev->conn->privateData;
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

E
Eric Blake 已提交
5698 5699
    virCheckFlags(0, NULL);

5700 5701 5702 5703 5704
    testDriverLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
    testDriverUnlock(driver);

    if (!obj) {
5705 5706 5707
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5708 5709 5710
        goto cleanup;
    }

5711
    ret = virNodeDeviceDefFormat(obj->def);
5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730

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) {
5731 5732 5733
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5734 5735 5736 5737
        goto cleanup;
    }

    if (obj->def->parent) {
5738
        ignore_value(VIR_STRDUP(ret, obj->def->parent));
5739
    } else {
5740 5741
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no parent for this device"));
5742 5743 5744 5745 5746 5747 5748 5749
    }

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

5750

5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764
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) {
5765 5766 5767
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795
        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) {
5796 5797 5798
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5799 5800 5801 5802
        goto cleanup;
    }

    for (caps = obj->def->caps; caps && ncaps < maxnames; caps = caps->next) {
5803
        if (VIR_STRDUP(names[ncaps++], virNodeDevCapTypeToString(caps->type)) < 0)
5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818
            goto cleanup;
    }
    ret = ncaps;

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

5819 5820 5821
static virNodeDevicePtr
testNodeDeviceCreateXML(virConnectPtr conn,
                        const char *xmlDesc,
E
Eric Blake 已提交
5822
                        unsigned int flags)
5823 5824 5825 5826 5827 5828 5829 5830 5831
{
    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 已提交
5832 5833
    virCheckFlags(0, NULL);

5834 5835
    testDriverLock(driver);

5836
    def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, NULL);
5837 5838 5839 5840 5841
    if (def == NULL) {
        goto cleanup;
    }

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

5846
    if (virNodeDeviceGetParentHost(&driver->devs,
5847 5848 5849 5850 5851 5852 5853 5854 5855
                                   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);
5856
    if (VIR_STRDUP(def->name, wwpn) < 0)
5857 5858 5859 5860 5861 5862 5863 5864 5865
        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;

5866
        caps->data.scsi_host.host = virRandomBits(10);
5867 5868 5869 5870
        caps = caps->next;
    }


5871
    if (!(obj = virNodeDeviceAssignDef(&driver->devs, def))) {
5872 5873 5874 5875 5876 5877 5878 5879
        goto cleanup;
    }
    virNodeDeviceObjUnlock(obj);

    dev = virGetNodeDevice(conn, def->name);
    def = NULL;
cleanup:
    testDriverUnlock(driver);
5880
    virNodeDeviceDefFree(def);
5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899
    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) {
5900
        virReportError(VIR_ERR_NO_NODE_DEVICE, NULL);
5901 5902 5903
        goto out;
    }

5904
    if (virNodeDeviceGetWWNs(obj->def, &wwnn, &wwpn) == -1) {
5905 5906 5907
        goto out;
    }

5908
    if (VIR_STRDUP(parent_name, obj->def->parent) < 0)
5909 5910 5911 5912 5913 5914 5915 5916 5917
        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 */
5918
    if (virNodeDeviceGetParentHost(&driver->devs,
5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937
                                   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;
}

5938 5939

/* Domain event implementations */
5940
static int
5941 5942 5943 5944
testConnectDomainEventRegister(virConnectPtr conn,
                               virConnectDomainEventCallback callback,
                               void *opaque,
                               virFreeCallback freecb)
5945 5946 5947 5948 5949
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
5950 5951 5952
    ret = virDomainEventStateRegister(conn,
                                      driver->domainEventState,
                                      callback, opaque, freecb);
5953 5954 5955 5956 5957
    testDriverUnlock(driver);

    return ret;
}

5958

5959
static int
5960 5961
testConnectDomainEventDeregister(virConnectPtr conn,
                                 virConnectDomainEventCallback callback)
5962 5963 5964 5965 5966
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
5967 5968 5969
    ret = virDomainEventStateDeregister(conn,
                                        driver->domainEventState,
                                        callback);
5970 5971 5972 5973 5974
    testDriverUnlock(driver);

    return ret;
}

5975 5976

static int
5977 5978 5979 5980 5981 5982
testConnectDomainEventRegisterAny(virConnectPtr conn,
                                  virDomainPtr dom,
                                  int eventID,
                                  virConnectDomainEventGenericCallback callback,
                                  void *opaque,
                                  virFreeCallback freecb)
5983 5984 5985 5986 5987
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
5988 5989 5990 5991
    if (virDomainEventStateRegisterID(conn,
                                      driver->domainEventState,
                                      dom, eventID,
                                      callback, opaque, freecb, &ret) < 0)
5992
        ret = -1;
5993 5994 5995 5996 5997 5998
    testDriverUnlock(driver);

    return ret;
}

static int
5999 6000
testConnectDomainEventDeregisterAny(virConnectPtr conn,
                                    int callbackID)
6001 6002 6003 6004 6005
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
6006 6007 6008
    ret = virDomainEventStateDeregisterID(conn,
                                          driver->domainEventState,
                                          callbackID);
6009 6010 6011 6012 6013 6014
    testDriverUnlock(driver);

    return ret;
}


6015 6016 6017 6018
/* driver must be locked before calling */
static void testDomainEventQueue(testConnPtr driver,
                                 virDomainEventPtr event)
{
6019
    virDomainEventStateQueue(driver->domainEventState, event);
6020 6021
}

6022 6023
static virDrvOpenStatus testSecretOpen(virConnectPtr conn,
                                       virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
6024 6025 6026 6027
                                       unsigned int flags)
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

6028 6029 6030
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

6031
    conn->secretPrivateData = conn->privateData;
6032 6033 6034 6035 6036 6037 6038
    return VIR_DRV_OPEN_SUCCESS;
}

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

6040 6041 6042

static virDrvOpenStatus testNWFilterOpen(virConnectPtr conn,
                                         virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
6043 6044 6045 6046
                                         unsigned int flags)
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

6047 6048 6049
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

6050
    conn->nwfilterPrivateData = conn->privateData;
6051 6052 6053 6054 6055 6056 6057 6058
    return VIR_DRV_OPEN_SUCCESS;
}

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

6059

6060 6061 6062
static int testConnectListAllDomains(virConnectPtr conn,
                                     virDomainPtr **domains,
                                     unsigned int flags)
6063 6064 6065 6066
{
    testConnPtr privconn = conn->privateData;
    int ret;

O
Osier Yang 已提交
6067
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
6068 6069

    testDriverLock(privconn);
6070 6071
    ret = virDomainObjListExport(privconn->domains, conn, domains,
                                 NULL, flags);
6072 6073 6074 6075 6076
    testDriverUnlock(privconn);

    return ret;
}

6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089
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) {
6090
        if (VIR_ALLOC_N(*cpumap, 1) < 0)
6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104
            goto cleanup;
        *cpumap[0] = 0x15;
    }

    if (online)
        *online = 3;

    ret = 8;

cleanup:
    testDriverUnlock(privconn);
    return ret;
}

6105 6106 6107 6108 6109 6110 6111 6112 6113 6114
static char *
testDomainScreenshot(virDomainPtr dom ATTRIBUTE_UNUSED,
                     virStreamPtr st,
                     unsigned int screen ATTRIBUTE_UNUSED,
                     unsigned int flags)
{
    char *ret = NULL;

    virCheckFlags(0, NULL);

6115
    if (VIR_STRDUP(ret, "image/png") < 0)
6116 6117
        return NULL;

6118
    if (virFDStreamOpenFile(st, PKGDATADIR "/libvirtLogo.png", 0, 0, O_RDONLY) < 0)
6119 6120 6121 6122 6123
        VIR_FREE(ret);

    return ret;
}

6124 6125 6126 6127 6128 6129 6130 6131 6132
static int
testConnectGetCPUModelNames(virConnectPtr conn ATTRIBUTE_UNUSED,
                            const char *arch,
                            char ***models,
                            unsigned int flags)
{
    virCheckFlags(0, -1);
    return cpuGetModels(arch, models);
}
6133

C
Cole Robinson 已提交
6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238
static int
testDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
    testConnPtr privconn = dom->conn->privateData;
    virDomainObjPtr vm = NULL;
    virDomainEventPtr event = NULL;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
                  VIR_DOMAIN_SAVE_RUNNING |
                  VIR_DOMAIN_SAVE_PAUSED, -1);

    testDriverLock(privconn);
    vm = virDomainObjListFindByName(privconn->domains, dom->name);
    testDriverUnlock(privconn);

    if (vm == NULL) {
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
        goto cleanup;
    }

    if (!virDomainObjIsActive(vm)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto cleanup;
    }

    if (!vm->persistent) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot do managed save for transient domain"));
        goto cleanup;
    }

    testDomainShutdownState(dom, vm, VIR_DOMAIN_SHUTOFF_SAVED);
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
    vm->hasManagedSave = true;

    ret = 0;
cleanup:
    if (vm)
        virObjectUnlock(vm);
    if (event) {
        testDriverLock(privconn);
        testDomainEventQueue(privconn, event);
        testDriverUnlock(privconn);
    }

    return ret;
}


static int
testDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    testConnPtr privconn = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(0, -1);

    testDriverLock(privconn);

    vm = virDomainObjListFindByName(privconn->domains, dom->name);
    if (vm == NULL) {
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
        goto cleanup;
    }

    ret = vm->hasManagedSave;
cleanup:
    if (vm)
        virObjectUnlock(vm);
    testDriverUnlock(privconn);
    return ret;
}

static int
testDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
{
    testConnPtr privconn = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(0, -1);

    testDriverLock(privconn);

    vm = virDomainObjListFindByName(privconn->domains, dom->name);
    if (vm == NULL) {
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
        goto cleanup;
    }

    vm->hasManagedSave = false;
    ret = 0;
cleanup:
    if (vm)
        virObjectUnlock(vm);
    testDriverUnlock(privconn);
    return ret;
}


6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593
/*
 * Snapshot APIs
 */

static virDomainSnapshotObjPtr
testSnapObjFromName(virDomainObjPtr vm,
                    const char *name)
{
    virDomainSnapshotObjPtr snap = NULL;
    snap = virDomainSnapshotFindByName(vm->snapshots, name);
    if (!snap)
        virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
                       _("no domain snapshot with matching name '%s'"),
                       name);
    return snap;
}

static virDomainSnapshotObjPtr
testSnapObjFromSnapshot(virDomainObjPtr vm,
                        virDomainSnapshotPtr snapshot)
{
    return testSnapObjFromName(vm, snapshot->name);
}

static virDomainObjPtr
testDomObjFromSnapshot(virDomainSnapshotPtr snapshot)
{
    return testDomObjFromDomain(snapshot->domain);
}

static int
testDomainSnapshotNum(virDomainPtr domain, unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int n = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
        goto cleanup;

    n = virDomainSnapshotObjListNum(vm->snapshots, NULL, flags);

cleanup:
    if (vm)
        virObjectUnlock(vm);
    return n;
}

static int
testDomainSnapshotListNames(virDomainPtr domain,
                            char **names,
                            int nameslen,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int n = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
        goto cleanup;

    n = virDomainSnapshotObjListGetNames(vm->snapshots, NULL, names, nameslen,
                                         flags);

cleanup:
    if (vm)
        virObjectUnlock(vm);
    return n;
}

static int
testDomainListAllSnapshots(virDomainPtr domain,
                           virDomainSnapshotPtr **snaps,
                           unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int n = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
        goto cleanup;

    n = virDomainListSnapshots(vm->snapshots, NULL, domain, snaps, flags);

cleanup:
    if (vm)
        virObjectUnlock(vm);
    return n;
}

static int
testDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
                                    char **names,
                                    int nameslen,
                                    unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    int n = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
        goto cleanup;

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    n = virDomainSnapshotObjListGetNames(vm->snapshots, snap, names, nameslen,
                                         flags);

cleanup:
    if (vm)
        virObjectUnlock(vm);
    return n;
}

static int
testDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot,
                              unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    int n = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
        goto cleanup;

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    n = virDomainSnapshotObjListNum(vm->snapshots, snap, flags);

cleanup:
    if (vm)
        virObjectUnlock(vm);
    return n;
}

static int
testDomainSnapshotListAllChildren(virDomainSnapshotPtr snapshot,
                                  virDomainSnapshotPtr **snaps,
                                  unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    int n = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
        goto cleanup;

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    n = virDomainListSnapshots(vm->snapshots, snap, snapshot->domain, snaps,
                               flags);

cleanup:
    if (vm)
        virObjectUnlock(vm);
    return n;
}

static virDomainSnapshotPtr
testDomainSnapshotLookupByName(virDomainPtr domain,
                               const char *name,
                               unsigned int flags)
{
    virDomainObjPtr vm;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr snapshot = NULL;

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
        goto cleanup;

    if (!(snap = testSnapObjFromName(vm, name)))
        goto cleanup;

    snapshot = virGetDomainSnapshot(domain, snap->def->name);

cleanup:
    if (vm)
        virObjectUnlock(vm);
    return snapshot;
}

static int
testDomainHasCurrentSnapshot(virDomainPtr domain,
                             unsigned int flags)
{
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(domain)))
        goto cleanup;

    ret = (vm->current_snapshot != NULL);

cleanup:
    if (vm)
        virObjectUnlock(vm);
    return ret;
}

static virDomainSnapshotPtr
testDomainSnapshotGetParent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr parent = NULL;

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
        goto cleanup;

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    if (!snap->def->parent) {
        virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
                       _("snapshot '%s' does not have a parent"),
                       snap->def->name);
        goto cleanup;
    }

    parent = virGetDomainSnapshot(snapshot->domain, snap->def->parent);

cleanup:
    if (vm)
        virObjectUnlock(vm);
    return parent;
}

static virDomainSnapshotPtr
testDomainSnapshotCurrent(virDomainPtr domain,
                          unsigned int flags)
{
    virDomainObjPtr vm;
    virDomainSnapshotPtr snapshot = NULL;

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
        goto cleanup;

    if (!vm->current_snapshot) {
        virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT, "%s",
                       _("the domain does not have a current snapshot"));
        goto cleanup;
    }

    snapshot = virGetDomainSnapshot(domain, vm->current_snapshot->def->name);

cleanup:
    if (vm)
        virObjectUnlock(vm);
    return snapshot;
}

static char *
testDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
                             unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    char *xml = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    char uuidstr[VIR_UUID_STRING_BUFLEN];

    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
        goto cleanup;

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    virUUIDFormat(snapshot->domain->uuid, uuidstr);

    xml = virDomainSnapshotDefFormat(uuidstr, snap->def, flags, 0);

cleanup:
    if (vm)
        virObjectUnlock(vm);
    return xml;
}

static int
testDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;
    virDomainSnapshotObjPtr snap = NULL;

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
        goto cleanup;

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    ret = (vm->current_snapshot &&
           STREQ(snapshot->name, vm->current_snapshot->def->name));

cleanup:
    if (vm)
        virObjectUnlock(vm);
    return ret;
}


static int
testDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot,
                              unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;
    virDomainSnapshotObjPtr snap = NULL;

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
        goto cleanup;

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    ret = 1;

cleanup:
    if (vm)
        virObjectUnlock(vm);
    return ret;
}

6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635
static int
testDomainSnapshotAlignDisks(virDomainObjPtr vm,
                             virDomainSnapshotDefPtr def,
                             unsigned int flags)
{
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
    int align_match = true;

    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) {
        align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
        align_match = false;
        if (virDomainObjIsActive(vm))
            def->state = VIR_DOMAIN_DISK_SNAPSHOT;
        else
            def->state = VIR_DOMAIN_SHUTOFF;
        def->memory = VIR_DOMAIN_SNAPSHOT_LOCATION_NONE;
    } else if (def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
        def->state = virDomainObjGetState(vm, NULL);
        align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
        align_match = false;
    } else {
        def->state = virDomainObjGetState(vm, NULL);
        def->memory = def->state == VIR_DOMAIN_SHUTOFF ?
                      VIR_DOMAIN_SNAPSHOT_LOCATION_NONE :
                      VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
    }

    return virDomainSnapshotAlignDisks(def, align_location, align_match);
}

static virDomainSnapshotPtr
testDomainSnapshotCreateXML(virDomainPtr domain,
                            const char *xmlDesc,
                            unsigned int flags)
{
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr vm = NULL;
    virDomainSnapshotDefPtr def = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr snapshot = NULL;
    virDomainEventPtr event = NULL;
    char *xml = NULL;
6636 6637
    bool update_current = true;
    bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
6638 6639 6640 6641 6642 6643 6644 6645
    unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;

    /*
     * DISK_ONLY: Not implemented yet
     * REUSE_EXT: Not implemented yet
     *
     * NO_METADATA: Explicitly not implemented
     *
6646
     * REDEFINE + CURRENT: Implemented
6647 6648 6649 6650 6651 6652
     * HALT: Implemented
     * QUIESCE: Nothing to do
     * ATOMIC: Nothing to do
     * LIVE: Nothing to do
     */
    virCheckFlags(
6653 6654
        VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
        VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
6655 6656 6657 6658 6659
        VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
        VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
        VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
        VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, NULL);

6660 6661 6662 6663 6664
    if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)))
        update_current = false;
    if (redefine)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;

6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680
    if (!(vm = testDomObjFromDomain(domain)))
        goto cleanup;

    if (!vm->persistent && (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT)) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot halt after transient domain snapshot"));
        goto cleanup;
    }

    if (!(def = virDomainSnapshotDefParseString(xmlDesc,
                                                privconn->caps,
                                                privconn->xmlopt,
                                                1 << VIR_DOMAIN_VIRT_TEST,
                                                parse_flags)))
        goto cleanup;

6681 6682 6683 6684 6685 6686 6687 6688 6689 6690
    if (redefine) {
        if (!virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
                                           &update_current, flags) < 0)
            goto cleanup;
    } else {
        if (!(def->dom = virDomainDefCopy(vm->def,
                                          privconn->caps,
                                          privconn->xmlopt,
                                          true)))
            goto cleanup;
6691

6692
        if (testDomainSnapshotAlignDisks(vm, def, flags) < 0)
6693 6694 6695
            goto cleanup;
    }

6696 6697 6698 6699
    if (!snap) {
        if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
            goto cleanup;
        def = NULL;
6700 6701
    }

6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715
    if (!redefine) {
        if (vm->current_snapshot &&
            (VIR_STRDUP(snap->def->parent,
                        vm->current_snapshot->def->name) < 0))
            goto cleanup;

        if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT) &&
            virDomainObjIsActive(vm)) {
            testDomainShutdownState(domain, vm,
                                    VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT);
            event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
                                    VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
        }
    }
6716 6717 6718 6719 6720 6721 6722

    snapshot = virGetDomainSnapshot(domain, snap->def->name);
cleanup:
    VIR_FREE(xml);
    if (vm) {
        if (snapshot) {
            virDomainSnapshotObjPtr other;
6723 6724
            if (update_current)
                vm->current_snapshot = snap;
6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088
            other = virDomainSnapshotFindByName(vm->snapshots,
                                                snap->def->parent);
            snap->parent = other;
            other->nchildren++;
            snap->sibling = other->first_child;
            other->first_child = snap;
        }
        virObjectUnlock(vm);
    }
    if (event) {
        testDriverLock(privconn);
        testDomainEventQueue(privconn, event);
        testDriverUnlock(privconn);
    }
    virDomainSnapshotDefFree(def);
    return snapshot;
}


typedef struct _testSnapRemoveData testSnapRemoveData;
typedef testSnapRemoveData *testSnapRemoveDataPtr;
struct _testSnapRemoveData {
    virDomainObjPtr vm;
    bool current;
};

static void
testDomainSnapshotDiscardAll(void *payload,
                          const void *name ATTRIBUTE_UNUSED,
                          void *data)
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapRemoveDataPtr curr = data;

    if (snap->def->current)
        curr->current = true;
    virDomainSnapshotObjListRemove(curr->vm->snapshots, snap);
}

typedef struct _testSnapReparentData testSnapReparentData;
typedef testSnapReparentData *testSnapReparentDataPtr;
struct _testSnapReparentData {
    virDomainSnapshotObjPtr parent;
    virDomainObjPtr vm;
    int err;
    virDomainSnapshotObjPtr last;
};

static void
testDomainSnapshotReparentChildren(void *payload,
                                   const void *name ATTRIBUTE_UNUSED,
                                   void *data)
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapReparentDataPtr rep = data;

    if (rep->err < 0) {
        return;
    }

    VIR_FREE(snap->def->parent);
    snap->parent = rep->parent;

    if (rep->parent->def &&
        VIR_STRDUP(snap->def->parent, rep->parent->def->name) < 0) {
        rep->err = -1;
        return;
    }

    if (!snap->sibling)
        rep->last = snap;
}

static int
testDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
                         unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotObjPtr parentsnap = NULL;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
                  VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
        return -1;

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    if (flags & (VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
                 VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)) {
        testSnapRemoveData rem;
        rem.vm = vm;
        rem.current = false;
        virDomainSnapshotForEachDescendant(snap,
                                           testDomainSnapshotDiscardAll,
                                           &rem);
        if (rem.current) {
            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) {
                snap->def->current = true;
            }
            vm->current_snapshot = snap;
        }
    } else if (snap->nchildren) {
        testSnapReparentData rep;
        rep.parent = snap->parent;
        rep.vm = vm;
        rep.err = 0;
        rep.last = NULL;
        virDomainSnapshotForEachChild(snap,
                                      testDomainSnapshotReparentChildren,
                                      &rep);
        if (rep.err < 0)
            goto cleanup;

        /* Can't modify siblings during ForEachChild, so do it now.  */
        snap->parent->nchildren += snap->nchildren;
        rep.last->sibling = snap->parent->first_child;
        snap->parent->first_child = snap->first_child;
    }

    if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) {
        snap->nchildren = 0;
        snap->first_child = NULL;
    } else {
        virDomainSnapshotDropParent(snap);
        if (snap == vm->current_snapshot) {
            if (snap->def->parent) {
                parentsnap = virDomainSnapshotFindByName(vm->snapshots,
                                                         snap->def->parent);
                if (!parentsnap) {
                    VIR_WARN("missing parent snapshot matching name '%s'",
                             snap->def->parent);
                } else {
                    parentsnap->def->current = true;
                }
            }
            vm->current_snapshot = parentsnap;
        }
        virDomainSnapshotObjListRemove(vm->snapshots, snap);
    }

    ret = 0;
cleanup:
    if (vm)
        virObjectUnlock(vm);
    return ret;
}

static int
testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                           unsigned int flags)
{
    testConnPtr privconn = snapshot->domain->conn->privateData;
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainEventPtr event = NULL;
    virDomainEventPtr event2 = NULL;
    virDomainDefPtr config = NULL;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
                  VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED |
                  VIR_DOMAIN_SNAPSHOT_REVERT_FORCE, -1);

    /* We have the following transitions, which create the following events:
     * 1. inactive -> inactive: none
     * 2. inactive -> running:  EVENT_STARTED
     * 3. inactive -> paused:   EVENT_STARTED, EVENT_PAUSED
     * 4. running  -> inactive: EVENT_STOPPED
     * 5. running  -> running:  none
     * 6. running  -> paused:   EVENT_PAUSED
     * 7. paused   -> inactive: EVENT_STOPPED
     * 8. paused   -> running:  EVENT_RESUMED
     * 9. paused   -> paused:   none
     * Also, several transitions occur even if we fail partway through,
     * and use of FORCE can cause multiple transitions.
     */

    if (!(vm = testDomObjFromSnapshot(snapshot)))
        return -1;

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    testDriverLock(privconn);

    if (!vm->persistent &&
        snap->def->state != VIR_DOMAIN_RUNNING &&
        snap->def->state != VIR_DOMAIN_PAUSED &&
        (flags & (VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
                  VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED)) == 0) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("transient domain needs to request run or pause "
                         "to revert to inactive snapshot"));
        goto cleanup;
    }

    if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_FORCE)) {
        if (!snap->def->dom) {
            virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY,
                           _("snapshot '%s' lacks domain '%s' rollback info"),
                           snap->def->name, vm->def->name);
            goto cleanup;
        }
        if (virDomainObjIsActive(vm) &&
            !(snap->def->state == VIR_DOMAIN_RUNNING
              || snap->def->state == VIR_DOMAIN_PAUSED) &&
            (flags & (VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
                      VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED))) {
            virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY, "%s",
                           _("must respawn guest to start inactive snapshot"));
            goto cleanup;
        }
    }


    if (vm->current_snapshot) {
        vm->current_snapshot->def->current = false;
        vm->current_snapshot = NULL;
    }

    snap->def->current = true;
    config = virDomainDefCopy(snap->def->dom,
                              privconn->caps, privconn->xmlopt, true);
    if (!config)
        goto cleanup;

    if (snap->def->state == VIR_DOMAIN_RUNNING ||
        snap->def->state == VIR_DOMAIN_PAUSED) {
        /* Transitions 2, 3, 5, 6, 8, 9 */
        bool was_running = false;
        bool was_stopped = false;

        if (virDomainObjIsActive(vm)) {
            /* Transitions 5, 6, 8, 9 */
            /* Check for ABI compatibility.  */
            if (!virDomainDefCheckABIStability(vm->def, config)) {
                virErrorPtr err = virGetLastError();

                if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_FORCE)) {
                    /* Re-spawn error using correct category. */
                    if (err->code == VIR_ERR_CONFIG_UNSUPPORTED)
                        virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY, "%s",
                                       err->str2);
                    goto cleanup;
                }

                virResetError(err);
                testDomainShutdownState(snapshot->domain, vm,
                                        VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT);
                event = virDomainEventNewFromObj(vm,
                            VIR_DOMAIN_EVENT_STOPPED,
                            VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
                if (event)
                    testDomainEventQueue(privconn, event);
                goto load;
            }

            if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
                /* Transitions 5, 6 */
                was_running = true;
                virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
                                     VIR_DOMAIN_PAUSED_FROM_SNAPSHOT);
                /* Create an event now in case the restore fails, so
                 * that user will be alerted that they are now paused.
                 * If restore later succeeds, we might replace this. */
                event = virDomainEventNewFromObj(vm,
                                VIR_DOMAIN_EVENT_SUSPENDED,
                                VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
            }
            virDomainObjAssignDef(vm, config, false, NULL);

        } else {
            /* Transitions 2, 3 */
        load:
            was_stopped = true;
            virDomainObjAssignDef(vm, config, false, NULL);
            if (testDomainStartState(privconn, vm,
                                VIR_DOMAIN_RUNNING_FROM_SNAPSHOT) < 0)
                goto cleanup;
            event = virDomainEventNewFromObj(vm,
                                VIR_DOMAIN_EVENT_STARTED,
                                VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
        }

        /* Touch up domain state.  */
        if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING) &&
            (snap->def->state == VIR_DOMAIN_PAUSED ||
             (flags & VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED))) {
            /* Transitions 3, 6, 9 */
            virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
                                 VIR_DOMAIN_PAUSED_FROM_SNAPSHOT);
            if (was_stopped) {
                /* Transition 3, use event as-is and add event2 */
                event2 = virDomainEventNewFromObj(vm,
                                VIR_DOMAIN_EVENT_SUSPENDED,
                                VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
            } /* else transition 6 and 9 use event as-is */
        } else {
            /* Transitions 2, 5, 8 */
            virDomainEventFree(event);
            event = NULL;

            if (was_stopped) {
                /* Transition 2 */
                event = virDomainEventNewFromObj(vm,
                                VIR_DOMAIN_EVENT_STARTED,
                                VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            } else if (was_running) {
                /* Transition 8 */
                event = virDomainEventNewFromObj(vm,
                                VIR_DOMAIN_EVENT_RESUMED,
                                VIR_DOMAIN_EVENT_RESUMED);
            }
        }
    } else {
        /* Transitions 1, 4, 7 */
        virDomainObjAssignDef(vm, config, false, NULL);

        if (virDomainObjIsActive(vm)) {
            /* Transitions 4, 7 */
            testDomainShutdownState(snapshot->domain, vm,
                                    VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT);
            event = virDomainEventNewFromObj(vm,
                                    VIR_DOMAIN_EVENT_STOPPED,
                                    VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
        }

        if (flags & (VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
                     VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED)) {
            /* Flush first event, now do transition 2 or 3 */
            bool paused = (flags & VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED) != 0;

            if (event)
                testDomainEventQueue(privconn, event);
            event = virDomainEventNewFromObj(vm,
                            VIR_DOMAIN_EVENT_STARTED,
                            VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            if (paused) {
                event2 = virDomainEventNewFromObj(vm,
                                VIR_DOMAIN_EVENT_SUSPENDED,
                                VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
            }
        }
    }

    vm->current_snapshot = snap;
    ret = 0;
cleanup:
    if (event) {
        testDomainEventQueue(privconn, event);
        if (event2)
            testDomainEventQueue(privconn, event2);
    }
    virObjectUnlock(vm);
    testDriverUnlock(privconn);

    return ret;
}


7089

7090
static virDriver testDriver = {
7091 7092
    .no = VIR_DRV_TEST,
    .name = "Test",
7093 7094 7095
    .connectOpen = testConnectOpen, /* 0.1.1 */
    .connectClose = testConnectClose, /* 0.1.1 */
    .connectGetVersion = testConnectGetVersion, /* 0.1.1 */
7096
    .connectGetHostname = testConnectGetHostname, /* 0.6.3 */
7097
    .connectGetMaxVcpus = testConnectGetMaxVcpus, /* 0.3.2 */
7098
    .nodeGetInfo = testNodeGetInfo, /* 0.1.1 */
7099 7100 7101 7102
    .connectGetCapabilities = testConnectGetCapabilities, /* 0.2.1 */
    .connectListDomains = testConnectListDomains, /* 0.1.1 */
    .connectNumOfDomains = testConnectNumOfDomains, /* 0.1.1 */
    .connectListAllDomains = testConnectListAllDomains, /* 0.9.13 */
7103
    .domainCreateXML = testDomainCreateXML, /* 0.1.4 */
7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117
    .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 */
7118 7119
    .domainGetState = testDomainGetState, /* 0.9.2 */
    .domainSave = testDomainSave, /* 0.3.2 */
7120
    .domainSaveFlags = testDomainSaveFlags, /* 0.9.4 */
7121
    .domainRestore = testDomainRestore, /* 0.3.2 */
7122
    .domainRestoreFlags = testDomainRestoreFlags, /* 0.9.4 */
7123
    .domainCoreDump = testDomainCoreDump, /* 0.3.2 */
7124
    .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */
7125 7126 7127 7128 7129 7130
    .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 */
7131 7132
    .connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
    .connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
7133 7134 7135 7136
    .domainCreate = testDomainCreate, /* 0.1.11 */
    .domainCreateWithFlags = testDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = testDomainDefineXML, /* 0.1.11 */
    .domainUndefine = testDomainUndefine, /* 0.1.11 */
7137
    .domainUndefineFlags = testDomainUndefineFlags, /* 0.9.4 */
7138 7139 7140
    .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
    .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
    .domainGetSchedulerType = testDomainGetSchedulerType, /* 0.3.2 */
7141 7142 7143 7144
    .domainGetSchedulerParameters = testDomainGetSchedulerParameters, /* 0.3.2 */
    .domainGetSchedulerParametersFlags = testDomainGetSchedulerParametersFlags, /* 0.9.2 */
    .domainSetSchedulerParameters = testDomainSetSchedulerParameters, /* 0.3.2 */
    .domainSetSchedulerParametersFlags = testDomainSetSchedulerParametersFlags, /* 0.9.2 */
7145 7146 7147
    .domainBlockStats = testDomainBlockStats, /* 0.7.0 */
    .domainInterfaceStats = testDomainInterfaceStats, /* 0.7.0 */
    .nodeGetCellsFreeMemory = testNodeGetCellsFreeMemory, /* 0.4.2 */
7148 7149 7150 7151
    .connectDomainEventRegister = testConnectDomainEventRegister, /* 0.6.0 */
    .connectDomainEventDeregister = testConnectDomainEventDeregister, /* 0.6.0 */
    .connectIsEncrypted = testConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = testConnectIsSecure, /* 0.7.3 */
7152 7153 7154
    .domainIsActive = testDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = testDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = testDomainIsUpdated, /* 0.8.6 */
7155 7156 7157
    .connectDomainEventRegisterAny = testConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = testConnectDomainEventDeregisterAny, /* 0.8.0 */
    .connectIsAlive = testConnectIsAlive, /* 0.9.8 */
7158
    .nodeGetCPUMap = testNodeGetCPUMap, /* 1.0.0 */
7159
    .domainScreenshot = testDomainScreenshot, /* 1.0.5 */
7160 7161
    .domainGetMetadata = testDomainGetMetadata, /* 1.1.3 */
    .domainSetMetadata = testDomainSetMetadata, /* 1.1.3 */
7162
    .connectGetCPUModelNames = testConnectGetCPUModelNames, /* 1.1.3 */
7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179
    .domainManagedSave = testDomainManagedSave, /* 1.1.4 */
    .domainHasManagedSaveImage = testDomainHasManagedSaveImage, /* 1.1.4 */
    .domainManagedSaveRemove = testDomainManagedSaveRemove, /* 1.1.4 */

    .domainSnapshotNum = testDomainSnapshotNum, /* 1.1.4 */
    .domainSnapshotListNames = testDomainSnapshotListNames, /* 1.1.4 */
    .domainListAllSnapshots = testDomainListAllSnapshots, /* 1.1.4 */
    .domainSnapshotGetXMLDesc = testDomainSnapshotGetXMLDesc, /* 1.1.4 */
    .domainSnapshotNumChildren = testDomainSnapshotNumChildren, /* 1.1.4 */
    .domainSnapshotListChildrenNames = testDomainSnapshotListChildrenNames, /* 1.1.4 */
    .domainSnapshotListAllChildren = testDomainSnapshotListAllChildren, /* 1.1.4 */
    .domainSnapshotLookupByName = testDomainSnapshotLookupByName, /* 1.1.4 */
    .domainHasCurrentSnapshot = testDomainHasCurrentSnapshot, /* 1.1.4 */
    .domainSnapshotGetParent = testDomainSnapshotGetParent, /* 1.1.4 */
    .domainSnapshotCurrent = testDomainSnapshotCurrent, /* 1.1.4 */
    .domainSnapshotIsCurrent = testDomainSnapshotIsCurrent, /* 1.1.4 */
    .domainSnapshotHasMetadata = testDomainSnapshotHasMetadata, /* 1.1.4 */
7180 7181 7182
    .domainSnapshotCreateXML = testDomainSnapshotCreateXML, /* 1.1.4 */
    .domainRevertToSnapshot = testDomainRevertToSnapshot, /* 1.1.4 */
    .domainSnapshotDelete = testDomainSnapshotDelete, /* 1.1.4 */
7183 7184 7185 7186
};

static virNetworkDriver testNetworkDriver = {
    "Test",
7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197
    .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 */
7198
    .networkUndefine = testNetworkUndefine, /* 0.3.2 */
7199
    .networkUpdate = testNetworkUpdate, /* 0.10.2 */
7200
    .networkCreate = testNetworkCreate, /* 0.3.2 */
7201 7202 7203 7204 7205 7206 7207
    .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 */
7208 7209
};

L
Laine Stump 已提交
7210 7211
static virInterfaceDriver testInterfaceDriver = {
    "Test",                     /* name */
7212 7213 7214 7215 7216 7217 7218 7219
    .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 */
7220 7221 7222 7223 7224 7225
    .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 */
7226 7227 7228
    .interfaceChangeBegin = testInterfaceChangeBegin,   /* 0.9.2 */
    .interfaceChangeCommit = testInterfaceChangeCommit,  /* 0.9.2 */
    .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */
L
Laine Stump 已提交
7229 7230 7231
};


7232 7233
static virStorageDriver testStorageDriver = {
    .name = "Test",
7234 7235
    .storageOpen = testStorageOpen, /* 0.4.1 */
    .storageClose = testStorageClose, /* 0.4.1 */
7236

7237 7238 7239 7240 7241 7242
    .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 */
7243 7244 7245
    .storagePoolLookupByName = testStoragePoolLookupByName, /* 0.5.0 */
    .storagePoolLookupByUUID = testStoragePoolLookupByUUID, /* 0.5.0 */
    .storagePoolLookupByVolume = testStoragePoolLookupByVolume, /* 0.5.0 */
7246 7247
    .storagePoolCreateXML = testStoragePoolCreateXML, /* 0.5.0 */
    .storagePoolDefineXML = testStoragePoolDefineXML, /* 0.5.0 */
7248 7249
    .storagePoolBuild = testStoragePoolBuild, /* 0.5.0 */
    .storagePoolUndefine = testStoragePoolUndefine, /* 0.5.0 */
7250
    .storagePoolCreate = testStoragePoolCreate, /* 0.5.0 */
7251 7252 7253 7254 7255 7256 7257
    .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 */
7258
    .storagePoolNumOfVolumes = testStoragePoolNumOfVolumes, /* 0.5.0 */
7259 7260 7261
    .storagePoolListVolumes = testStoragePoolListVolumes, /* 0.5.0 */
    .storagePoolListAllVolumes = testStoragePoolListAllVolumes, /* 0.10.2 */

7262 7263 7264 7265 7266 7267 7268 7269 7270
    .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 */
7271 7272
    .storagePoolIsActive = testStoragePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = testStoragePoolIsPersistent, /* 0.7.3 */
7273 7274
};

7275
static virNodeDeviceDriver testNodeDeviceDriver = {
7276
    .name = "Test",
7277 7278
    .nodeDeviceOpen = testNodeDeviceOpen, /* 0.6.0 */
    .nodeDeviceClose = testNodeDeviceClose, /* 0.6.0 */
7279 7280 7281 7282 7283 7284 7285 7286 7287 7288

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

7291 7292
static virSecretDriver testSecretDriver = {
    .name = "Test",
7293 7294
    .secretOpen = testSecretOpen, /* 0.7.1 */
    .secretClose = testSecretClose, /* 0.7.1 */
7295
};
7296 7297


7298 7299
static virNWFilterDriver testNWFilterDriver = {
    .name = "Test",
7300 7301
    .nwfilterOpen = testNWFilterOpen, /* 0.8.0 */
    .nwfilterClose = testNWFilterClose, /* 0.8.0 */
7302 7303
};

7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
    if (virRegisterDriver(&testDriver) < 0)
        return -1;
    if (virRegisterNetworkDriver(&testNetworkDriver) < 0)
        return -1;
L
Laine Stump 已提交
7316 7317
    if (virRegisterInterfaceDriver(&testInterfaceDriver) < 0)
        return -1;
7318 7319
    if (virRegisterStorageDriver(&testStorageDriver) < 0)
        return -1;
7320
    if (virRegisterNodeDeviceDriver(&testNodeDeviceDriver) < 0)
7321
        return -1;
7322 7323
    if (virRegisterSecretDriver(&testSecretDriver) < 0)
        return -1;
7324 7325
    if (virRegisterNWFilterDriver(&testNWFilterDriver) < 0)
        return -1;
7326

7327 7328
    return 0;
}