test_driver.c 198.1 KB
Newer Older
1
/*
2
 * test_driver.c: A "mock" hypervisor for use by application unit tests
3
 *
4
 * Copyright (C) 2006-2015 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"
J
John Ferlan 已提交
44
#include "virnetworkobj.h"
L
Laine Stump 已提交
45
#include "interface_conf.h"
46
#include "domain_conf.h"
47
#include "domain_event.h"
48
#include "network_event.h"
49
#include "snapshot_conf.h"
50
#include "virfdstream.h"
C
Cole Robinson 已提交
51
#include "storage_conf.h"
J
John Ferlan 已提交
52
#include "virstorageobj.h"
53
#include "storage_event.h"
54
#include "node_device_conf.h"
J
John Ferlan 已提交
55
#include "virnodedeviceobj.h"
56
#include "node_device_event.h"
57
#include "virxml.h"
58
#include "virthread.h"
59
#include "virlog.h"
E
Eric Blake 已提交
60
#include "virfile.h"
61
#include "virtypedparam.h"
62
#include "virrandom.h"
63
#include "virstring.h"
64
#include "cpu/cpu.h"
65
#include "virauth.h"
66
#include "viratomic.h"
67
#include "virdomainobjlist.h"
J
John Ferlan 已提交
68
#include "virinterfaceobj.h"
69
#include "virhostcpu.h"
70

71 72
#define VIR_FROM_THIS VIR_FROM_TEST

73 74
VIR_LOG_INIT("test.test_driver");

75

76 77 78 79
#define MAX_CPUS 128

struct _testCell {
    unsigned long mem;
80
    unsigned long freeMem;
81
    int numCpus;
82
    virCapsHostNUMACellCPU cpus[MAX_CPUS];
83 84 85 86 87
};
typedef struct _testCell testCell;
typedef struct _testCell *testCellPtr;

#define MAX_CELLS 128
88

89 90 91 92 93 94 95
struct _testAuth {
    char *username;
    char *password;
};
typedef struct _testAuth testAuth;
typedef struct _testAuth *testAuthPtr;

96
struct _testDriver {
97
    virMutex lock;
98

99
    virNodeInfo nodeInfo;
100
    virInterfaceObjListPtr ifaces;
101
    bool transaction_running;
102
    virInterfaceObjListPtr backupIfaces;
C
Cole Robinson 已提交
103
    virStoragePoolObjList pools;
104
    virNodeDeviceObjListPtr devs;
105 106
    int numCells;
    testCell cells[MAX_CELLS];
107 108
    size_t numAuths;
    testAuthPtr auths;
109

110 111 112
    /* virAtomic access only */
    volatile int nextDomID;

113 114 115 116 117 118 119 120 121 122
    /* immutable pointer, immutable object after being initialized with
     * testBuildCapabilities */
    virCapsPtr caps;

    /* immutable pointer, immutable object */
    virDomainXMLOptionPtr xmlopt;

    /* immutable pointer, self-locking APIs */
    virDomainObjListPtr domains;
    virNetworkObjListPtr networks;
123
    virObjectEventStatePtr eventState;
124
};
125 126
typedef struct _testDriver testDriver;
typedef testDriver *testDriverPtr;
127

128
static testDriverPtr defaultConn;
129
static int defaultConnections;
130
static virMutex defaultLock = VIR_MUTEX_INITIALIZER;
131

132
#define TEST_MODEL "i686"
133
#define TEST_EMULATOR "/usr/bin/test-hv"
134

135
static const virNodeInfo defaultNodeInfo = {
136
    TEST_MODEL,
137 138 139 140 141 142 143
    1024*1024*3, /* 3 GB */
    16,
    1400,
    2,
    2,
    2,
    2,
144 145
};

146 147 148 149 150 151 152 153 154
static void
testDriverFree(testDriverPtr driver)
{
    if (!driver)
        return;

    virObjectUnref(driver->caps);
    virObjectUnref(driver->xmlopt);
    virObjectUnref(driver->domains);
155
    virNodeDeviceObjListFree(driver->devs);
156
    virObjectUnref(driver->networks);
157
    virInterfaceObjListFree(driver->ifaces);
158
    virStoragePoolObjListFree(&driver->pools);
159
    virObjectUnref(driver->eventState);
160 161 162 163 164
    virMutexUnlock(&driver->lock);
    virMutexDestroy(&driver->lock);

    VIR_FREE(driver);
}
165

166

167
static void testDriverLock(testDriverPtr driver)
168
{
169
    virMutexLock(&driver->lock);
170 171
}

172
static void testDriverUnlock(testDriverPtr driver)
173
{
174
    virMutexUnlock(&driver->lock);
175 176
}

177 178 179 180 181 182 183 184 185
static void testObjectEventQueue(testDriverPtr driver,
                                 virObjectEventPtr event)
{
    if (!event)
        return;

    virObjectEventStateQueue(driver->eventState, event);
}

186 187 188 189 190 191
#define TEST_NAMESPACE_HREF "http://libvirt.org/schemas/domain/test/1.0"

typedef struct _testDomainNamespaceDef testDomainNamespaceDef;
typedef testDomainNamespaceDef *testDomainNamespaceDefPtr;
struct _testDomainNamespaceDef {
    int runstate;
192
    bool transient;
C
Cole Robinson 已提交
193
    bool hasManagedSave;
194 195 196

    unsigned int num_snap_nodes;
    xmlNodePtr *snap_nodes;
197 198 199 200 201 202
};

static void
testDomainDefNamespaceFree(void *data)
{
    testDomainNamespaceDefPtr nsdata = data;
203 204 205 206 207 208 209 210 211
    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);
212 213 214 215 216 217 218 219 220 221
    VIR_FREE(nsdata);
}

static int
testDomainDefNamespaceParse(xmlDocPtr xml ATTRIBUTE_UNUSED,
                            xmlNodePtr root ATTRIBUTE_UNUSED,
                            xmlXPathContextPtr ctxt,
                            void **data)
{
    testDomainNamespaceDefPtr nsdata = NULL;
222 223 224
    xmlNodePtr *nodes = NULL;
    int tmp, n;
    size_t i;
225 226 227 228 229 230 231 232 233 234 235 236 237
    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;

238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
    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);

257 258 259 260 261 262 263
    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 已提交
264 265 266 267 268 269 270
    tmp = virXPathBoolean("boolean(./test:hasmanagedsave)", ctxt);
    if (tmp == -1) {
        virReportError(VIR_ERR_XML_ERROR, "%s", _("invalid hasmanagedsave"));
        goto error;
    }
    nsdata->hasManagedSave = tmp;

271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
    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;
    }

287 288 289 290 291
    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 已提交
292 293 294 295 296
    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;
    }
297

298 299 300
    *data = nsdata;
    return 0;

301
 error:
302
    VIR_FREE(nodes);
303 304 305
    testDomainDefNamespaceFree(nsdata);
    return -1;
}
306

307
static virCapsPtr
308 309
testBuildCapabilities(virConnectPtr conn)
{
310
    testDriverPtr privconn = conn->privateData;
311 312
    virCapsPtr caps;
    virCapsGuestPtr guest;
313 314
    int guest_types[] = { VIR_DOMAIN_OSTYPE_HVM,
                          VIR_DOMAIN_OSTYPE_XEN };
315
    size_t i, j;
316

317
    if ((caps = virCapabilitiesNew(VIR_ARCH_I686, false, false)) == NULL)
318
        goto error;
319

320
    if (virCapabilitiesAddHostFeature(caps, "pae") < 0)
321
        goto error;
322
    if (virCapabilitiesAddHostFeature(caps, "nonpae") < 0)
323
        goto error;
324

325 326 327 328 329 330
    if (VIR_ALLOC_N(caps->host.pagesSize, 2) < 0)
        goto error;

    caps->host.pagesSize[caps->host.nPagesSize++] = 4;
    caps->host.pagesSize[caps->host.nPagesSize++] = 2048;

331
    for (i = 0; i < privconn->numCells; i++) {
332
        virCapsHostNUMACellCPUPtr cpu_cells;
333 334
        virCapsHostNUMACellPageInfoPtr pages;
        size_t nPages;
335

336 337 338 339 340 341 342
        if (VIR_ALLOC_N(cpu_cells, privconn->cells[i].numCpus) < 0 ||
            VIR_ALLOC_N(pages, caps->host.nPagesSize) < 0) {
                VIR_FREE(cpu_cells);
                goto error;
            }

        nPages = caps->host.nPagesSize;
343 344 345 346

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

347 348 349 350
        for (j = 0; j < nPages; j++)
            pages[j].size = caps->host.pagesSize[j];

        pages[0].avail = privconn->cells[i].mem / pages[0].size;
351

352
        if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].mem,
353
                                           privconn->cells[i].numCpus,
354
                                           cpu_cells, 0, NULL, nPages, pages) < 0)
355
            goto error;
356 357
    }

358
    for (i = 0; i < ARRAY_CARDINALITY(guest_types); i++) {
359 360
        if ((guest = virCapabilitiesAddGuest(caps,
                                             guest_types[i],
361
                                             VIR_ARCH_I686,
362 363 364 365
                                             TEST_EMULATOR,
                                             NULL,
                                             0,
                                             NULL)) == NULL)
366
            goto error;
367

368
        if (virCapabilitiesAddGuestDomain(guest,
369
                                          VIR_DOMAIN_VIRT_TEST,
370 371 372 373
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
374
            goto error;
375

376
        if (virCapabilitiesAddGuestFeature(guest, "pae", true, true) == NULL)
377
            goto error;
378
        if (virCapabilitiesAddGuestFeature(guest, "nonpae", true, true) == NULL)
379
            goto error;
380 381
    }

382 383
    caps->host.nsecModels = 1;
    if (VIR_ALLOC_N(caps->host.secModels, caps->host.nsecModels) < 0)
384
        goto error;
385 386
    if (VIR_STRDUP(caps->host.secModels[0].model, "testSecurity") < 0)
        goto error;
387

388 389
    if (VIR_STRDUP(caps->host.secModels[0].doi, "") < 0)
        goto error;
390

391
    return caps;
392

393
 error:
394
    virObjectUnref(caps);
395
    return NULL;
396 397
}

398

399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
static testDriverPtr
testDriverNew(void)
{
    virDomainXMLNamespace ns = {
        .parse = testDomainDefNamespaceParse,
        .free = testDomainDefNamespaceFree,
    };
    testDriverPtr ret;

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

    if (virMutexInit(&ret->lock) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot initialize mutex"));
        goto error;
    }

417
    if (!(ret->xmlopt = virDomainXMLOptionNew(NULL, NULL, &ns, NULL, NULL)) ||
418
        !(ret->eventState = virObjectEventStateNew()) ||
419
        !(ret->ifaces = virInterfaceObjListNew()) ||
420
        !(ret->domains = virDomainObjListNew()) ||
421 422
        !(ret->networks = virNetworkObjListNew()) ||
        !(ret->devs = virNodeDeviceObjListNew()))
423 424
        goto error;

425
    virAtomicIntSet(&ret->nextDomID, 1);
426 427 428 429 430 431 432 433 434

    return ret;

 error:
    testDriverFree(ret);
    return NULL;
}


435 436
static const char *defaultConnXML =
"<node>"
437 438
"<domain type='test'>"
"  <name>test</name>"
439
"  <uuid>6695eb01-f6a4-8304-79aa-97f2502e193f</uuid>"
440 441 442 443 444 445
"  <memory>8388608</memory>"
"  <currentMemory>2097152</currentMemory>"
"  <vcpu>2</vcpu>"
"  <os>"
"    <type>hvm</type>"
"  </os>"
446 447
"</domain>"
""
448 449
"<network>"
"  <name>default</name>"
450
"  <uuid>dd8fe884-6c02-601e-7551-cca97df1c5df</uuid>"
451
"  <bridge name='virbr0'/>"
452 453 454
"  <forward/>"
"  <ip address='192.168.122.1' netmask='255.255.255.0'>"
"    <dhcp>"
455
"      <range start='192.168.122.2' end='192.168.122.254'/>"
456 457
"    </dhcp>"
"  </ip>"
458 459
"</network>"
""
L
Laine Stump 已提交
460 461 462 463 464 465 466 467
"<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>"
468 469
"</interface>"
""
C
Cole Robinson 已提交
470 471
"<pool type='dir'>"
"  <name>default-pool</name>"
472
"  <uuid>dfe224cb-28fb-8dd0-c4b2-64eb3f0f4566</uuid>"
C
Cole Robinson 已提交
473 474 475
"  <target>"
"    <path>/default-pool</path>"
"  </target>"
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
"</pool>"
""
"<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>"
494
"<device>"
495
"  <name>scsi_host1</name>"
496 497 498
"  <parent>computer</parent>"
"  <capability type='scsi_host'>"
"    <host>1</host>"
499
"    <unique_id>0</unique_id>"
500 501 502
"    <capability type='fc_host'>"
"      <wwnn>2000000012341234</wwnn>"
"      <wwpn>1000000012341234</wwpn>"
503 504 505 506
"      <fabric_wwn>2000000043214321</fabric_wwn>"
"    </capability>"
"    <capability type='vport_ops'>"
"      <max_vports>127</max_vports>"
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
"      <vports>1</vports>"
"    </capability>"
"  </capability>"
"</device>"
"<device>"
"  <name>scsi_host2</name>"
"  <parent>computer</parent>"
"  <capability type='scsi_host'>"
"    <host>2</host>"
"    <unique_id>1</unique_id>"
"    <capability type='fc_host'>"
"      <wwnn>2000000056785678</wwnn>"
"      <wwpn>1000000056785678</wwpn>"
"      <fabric_wwn>2000000087658765</fabric_wwn>"
"    </capability>"
"    <capability type='vport_ops'>"
"      <max_vports>127</max_vports>"
524
"      <vports>0</vports>"
525 526 527
"    </capability>"
"  </capability>"
"</device>"
528 529 530 531 532 533 534 535 536 537 538 539 540
"<device>"
"  <name>scsi_host11</name>"
"  <parent>scsi_host1</parent>"
"  <capability type='scsi_host'>"
"    <host>11</host>"
"    <unique_id>10</unique_id>"
"    <capability type='fc_host'>"
"      <wwnn>2000000034563456</wwnn>"
"      <wwpn>1000000034563456</wwpn>"
"      <fabric_wwn>2000000043214321</fabric_wwn>"
"    </capability>"
"  </capability>"
 "</device>"
541 542
"</node>";

C
Cole Robinson 已提交
543

544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
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";

567
static const unsigned long long defaultPoolCap = (100 * 1024 * 1024 * 1024ull);
568
static const unsigned long long defaultPoolAlloc;
C
Cole Robinson 已提交
569

570
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool);
571
static int testNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
572

573 574 575 576
static virDomainObjPtr
testDomObjFromDomain(virDomainPtr domain)
{
    virDomainObjPtr vm;
577
    testDriverPtr driver = domain->conn->privateData;
578 579
    char uuidstr[VIR_UUID_STRING_BUFLEN];

580
    vm = virDomainObjListFindByUUIDRef(driver->domains, domain->uuid);
581 582 583 584 585 586 587 588 589 590
    if (!vm) {
        virUUIDFormat(domain->uuid, uuidstr);
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching uuid '%s' (%s)"),
                       uuidstr, domain->name);
    }

    return vm;
}

591
static char *
592 593
testDomainGenerateIfname(virDomainDefPtr domdef)
{
594
    int maxif = 1024;
595 596
    int ifctr;
    size_t i;
597 598 599 600 601

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

602
        if (virAsprintf(&ifname, "testnet%d", ifctr) < 0)
603 604 605
            return NULL;

        /* Generate network interface names */
606
        for (i = 0; i < domdef->nnets; i++) {
607
            if (domdef->nets[i]->ifname &&
608
                STREQ(domdef->nets[i]->ifname, ifname)) {
609 610 611 612 613 614 615
                found = 1;
                break;
            }
        }

        if (!found)
            return ifname;
616
        VIR_FREE(ifname);
617 618
    }

619 620
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Exceeded max iface limit %d"), maxif);
621 622 623
    return NULL;
}

624
static int
625
testDomainGenerateIfnames(virDomainDefPtr domdef)
626
{
627
    size_t i = 0;
628 629 630 631 632 633

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

634
        ifname = testDomainGenerateIfname(domdef);
635
        if (!ifname)
636
            return -1;
637 638 639 640

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

641
    return 0;
642 643
}

644

645 646
static void
testDomainShutdownState(virDomainPtr domain,
J
Jiri Denemark 已提交
647 648
                        virDomainObjPtr privdom,
                        virDomainShutoffReason reason)
649
{
650
    virDomainObjRemoveTransientDef(privdom);
J
Jiri Denemark 已提交
651
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF, reason);
652

653 654 655 656
    if (domain)
        domain->id = -1;
}

657
/* Set up domain runtime state */
658
static int
659
testDomainStartState(testDriverPtr privconn,
J
Jiri Denemark 已提交
660 661
                     virDomainObjPtr dom,
                     virDomainRunningReason reason)
662
{
663
    int ret = -1;
664

J
Jiri Denemark 已提交
665
    virDomainObjSetState(dom, VIR_DOMAIN_RUNNING, reason);
666
    dom->def->id = virAtomicIntAdd(&privconn->nextDomID, 1);
667

668
    if (virDomainObjSetDefTransient(privconn->caps,
669
                                    privconn->xmlopt,
670
                                    dom) < 0) {
671 672 673
        goto cleanup;
    }

C
Cole Robinson 已提交
674
    dom->hasManagedSave = false;
675
    ret = 0;
676
 cleanup:
677
    if (ret < 0)
J
Jiri Denemark 已提交
678
        testDomainShutdownState(NULL, dom, VIR_DOMAIN_SHUTOFF_FAILED);
679
    return ret;
680
}
681

682

683
static char *testBuildFilename(const char *relativeTo,
684 685
                               const char *filename)
{
686 687
    char *offset;
    int baseLen;
688 689
    char *ret;

690
    if (!filename || filename[0] == '\0')
691
        return NULL;
692 693 694 695
    if (filename[0] == '/') {
        ignore_value(VIR_STRDUP(ret, filename));
        return ret;
    }
696

697
    offset = strrchr(relativeTo, '/');
698
    if ((baseLen = (offset-relativeTo+1))) {
699
        char *absFile;
C
Chris Lalancette 已提交
700 701
        int totalLen = baseLen + strlen(filename) + 1;
        if (VIR_ALLOC_N(absFile, totalLen) < 0)
702
            return NULL;
C
Chris Lalancette 已提交
703 704 705 706
        if (virStrncpy(absFile, relativeTo, baseLen, totalLen) == NULL) {
            VIR_FREE(absFile);
            return NULL;
        }
707 708 709
        strcat(absFile, filename);
        return absFile;
    } else {
710 711
        ignore_value(VIR_STRDUP(ret, filename));
        return ret;
712
    }
713 714
}

C
Cole Robinson 已提交
715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745
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;
    }

746
 error:
C
Cole Robinson 已提交
747 748 749 750 751
    xmlFreeDoc(doc);
    VIR_FREE(absFile);
    return ret;
}

752 753 754
static int
testParseNodeInfo(virNodeInfoPtr nodeInfo, xmlXPathContextPtr ctxt)
{
755
    char *str;
756 757
    long l;
    int ret;
758

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

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

777
    ret = virXPathLong("string(/node/cpu/cores[1])", ctxt, &l);
778 779 780
    if (ret == 0) {
        nodeInfo->cores = l;
    } else if (ret == -2) {
781 782
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu cores value"));
783
        goto error;
784 785
    }

786
    ret = virXPathLong("string(/node/cpu/threads[1])", ctxt, &l);
787 788 789
    if (ret == 0) {
        nodeInfo->threads = l;
    } else if (ret == -2) {
790 791
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu threads value"));
792
        goto error;
793
    }
794

795 796
    nodeInfo->cpus = (nodeInfo->cores * nodeInfo->threads *
                      nodeInfo->sockets * nodeInfo->nodes);
797
    ret = virXPathLong("string(/node/cpu/active[1])", ctxt, &l);
798
    if (ret == 0) {
799
        if (l < nodeInfo->cpus)
800
            nodeInfo->cpus = l;
801
    } else if (ret == -2) {
802 803
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu active value"));
804
        goto error;
805
    }
806
    ret = virXPathLong("string(/node/cpu/mhz[1])", ctxt, &l);
807 808 809
    if (ret == 0) {
        nodeInfo->mhz = l;
    } else if (ret == -2) {
810 811
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu mhz value"));
812
        goto error;
813 814
    }

815
    str = virXPathString("string(/node/cpu/model[1])", ctxt);
816
    if (str != NULL) {
C
Chris Lalancette 已提交
817
        if (virStrcpyStatic(nodeInfo->model, str) == NULL) {
818 819
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Model %s too big for destination"), str);
C
Chris Lalancette 已提交
820 821 822
            VIR_FREE(str);
            goto error;
        }
823
        VIR_FREE(str);
824 825
    }

826
    ret = virXPathLong("string(/node/memory[1])", ctxt, &l);
827 828 829
    if (ret == 0) {
        nodeInfo->memory = l;
    } else if (ret == -2) {
830 831
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node memory value"));
832
        goto error;
833
    }
834

835
    return 0;
836
 error:
837 838 839
    return -1;
}

840
static int
841
testParseDomainSnapshots(testDriverPtr privconn,
842 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 880 881 882 883 884 885 886 887 888 889 890 891
                         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,
                                            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;
892
 error:
893 894 895
    return ret;
}

896
static int
897
testParseDomains(testDriverPtr privconn,
C
Cole Robinson 已提交
898 899
                 const char *file,
                 xmlXPathContextPtr ctxt)
900 901 902 903 904 905 906
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virDomainObjPtr obj;

    num = virXPathNodeSet("/node/domain", ctxt, &nodes);
907
    if (num < 0)
908 909
        goto error;

910
    for (i = 0; i < num; i++) {
911
        virDomainDefPtr def;
912
        testDomainNamespaceDefPtr nsdata;
C
Cole Robinson 已提交
913 914 915 916 917
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file, "domain");
        if (!node)
            goto error;

        def = virDomainDefParseNode(ctxt->doc, node,
918
                                    privconn->caps, privconn->xmlopt, NULL,
919
                                    VIR_DOMAIN_DEF_PARSE_INACTIVE);
C
Cole Robinson 已提交
920 921
        if (!def)
            goto error;
922

923
        if (testDomainGenerateIfnames(def) < 0 ||
924
            !(obj = virDomainObjListAdd(privconn->domains,
925
                                        def,
926
                                        privconn->xmlopt,
927
                                        0, NULL))) {
928
            virDomainDefFree(def);
929 930
            goto error;
        }
931

932 933 934 935 936
        if (testParseDomainSnapshots(privconn, obj, file, ctxt) < 0) {
            virObjectUnlock(obj);
            goto error;
        }

937
        nsdata = def->namespaceData;
938
        obj->persistent = !nsdata->transient;
C
Cole Robinson 已提交
939
        obj->hasManagedSave = nsdata->hasManagedSave;
940 941 942 943 944 945 946 947 948

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

952
        virObjectUnlock(obj);
953
    }
954

955
    ret = 0;
956
 error:
957 958 959 960
    VIR_FREE(nodes);
    return ret;
}

961

962
static int
963
testParseNetworks(testDriverPtr privconn,
C
Cole Robinson 已提交
964 965
                  const char *file,
                  xmlXPathContextPtr ctxt)
966 967 968 969 970 971 972
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virNetworkObjPtr obj;

    num = virXPathNodeSet("/node/network", ctxt, &nodes);
973
    if (num < 0)
974
        goto error;
975 976

    for (i = 0; i < num; i++) {
977
        virNetworkDefPtr def;
C
Cole Robinson 已提交
978 979 980
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file, "network");
        if (!node)
            goto error;
981

C
Cole Robinson 已提交
982 983 984
        def = virNetworkDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
985

986
        if (!(obj = virNetworkObjAssignDef(privconn->networks, def, 0))) {
987 988
            virNetworkDefFree(def);
            goto error;
989
        }
990 991

        obj->active = 1;
992
        virNetworkObjEndAPI(&obj);
993
    }
994

995
    ret = 0;
996
 error:
997 998 999 1000
    VIR_FREE(nodes);
    return ret;
}

1001

1002
static int
1003
testParseInterfaces(testDriverPtr privconn,
C
Cole Robinson 已提交
1004 1005
                    const char *file,
                    xmlXPathContextPtr ctxt)
1006 1007 1008 1009 1010 1011 1012
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virInterfaceObjPtr obj;

    num = virXPathNodeSet("/node/interface", ctxt, &nodes);
1013
    if (num < 0)
L
Laine Stump 已提交
1014
        goto error;
1015 1016

    for (i = 0; i < num; i++) {
L
Laine Stump 已提交
1017
        virInterfaceDefPtr def;
C
Cole Robinson 已提交
1018 1019 1020 1021
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "interface");
        if (!node)
            goto error;
L
Laine Stump 已提交
1022

C
Cole Robinson 已提交
1023 1024 1025
        def = virInterfaceDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
1026

1027
        if (!(obj = virInterfaceObjListAssignDef(privconn->ifaces, def))) {
L
Laine Stump 已提交
1028 1029 1030
            virInterfaceDefFree(def);
            goto error;
        }
1031

1032
        virInterfaceObjSetActive(obj, true);
1033
        virInterfaceObjEndAPI(&obj);
1034 1035 1036
    }

    ret = 0;
1037
 error:
1038 1039 1040 1041 1042
    VIR_FREE(nodes);
    return ret;
}

static int
C
Cole Robinson 已提交
1043
testOpenVolumesForPool(const char *file,
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059
                       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);
1060
    if (num < 0)
1061 1062 1063
        goto error;

    for (i = 0; i < num; i++) {
C
Cole Robinson 已提交
1064 1065 1066 1067
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "volume");
        if (!node)
            goto error;
1068

1069
        def = virStorageVolDefParseNode(pool->def, ctxt->doc, node, 0);
C
Cole Robinson 已提交
1070 1071
        if (!def)
            goto error;
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081

        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;
1082 1083
        if (VIR_APPEND_ELEMENT_COPY(pool->volumes.objs, pool->volumes.count, def) < 0)
            goto error;
1084

1085
        pool->def->allocation += def->target.allocation;
1086 1087 1088
        pool->def->available = (pool->def->capacity -
                                pool->def->allocation);
        def = NULL;
L
Laine Stump 已提交
1089 1090
    }

1091
    ret = 0;
1092
 error:
1093 1094 1095 1096 1097 1098
    virStorageVolDefFree(def);
    VIR_FREE(nodes);
    return ret;
}

static int
1099
testParseStorage(testDriverPtr privconn,
C
Cole Robinson 已提交
1100 1101
                 const char *file,
                 xmlXPathContextPtr ctxt)
1102 1103 1104 1105 1106 1107 1108
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virStoragePoolObjPtr obj;

    num = virXPathNodeSet("/node/pool", ctxt, &nodes);
1109
    if (num < 0)
C
Cole Robinson 已提交
1110
        goto error;
1111 1112

    for (i = 0; i < num; i++) {
C
Cole Robinson 已提交
1113
        virStoragePoolDefPtr def;
C
Cole Robinson 已提交
1114 1115 1116 1117
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "pool");
        if (!node)
            goto error;
C
Cole Robinson 已提交
1118

C
Cole Robinson 已提交
1119 1120 1121
        def = virStoragePoolDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
C
Cole Robinson 已提交
1122

1123
        if (!(obj = virStoragePoolObjAssignDef(&privconn->pools,
C
Cole Robinson 已提交
1124 1125 1126 1127 1128
                                                def))) {
            virStoragePoolDefFree(def);
            goto error;
        }

1129 1130
        if (testStoragePoolObjSetDefaults(obj) == -1) {
            virStoragePoolObjUnlock(obj);
C
Cole Robinson 已提交
1131
            goto error;
1132
        }
1133
        obj->active = 1;
1134 1135

        /* Find storage volumes */
C
Cole Robinson 已提交
1136
        if (testOpenVolumesForPool(file, ctxt, obj, i+1) < 0) {
1137
            virStoragePoolObjUnlock(obj);
1138 1139 1140
            goto error;
        }

1141
        virStoragePoolObjUnlock(obj);
C
Cole Robinson 已提交
1142 1143
    }

1144
    ret = 0;
1145
 error:
1146 1147 1148 1149 1150
    VIR_FREE(nodes);
    return ret;
}

static int
1151
testParseNodedevs(testDriverPtr privconn,
C
Cole Robinson 已提交
1152 1153
                  const char *file,
                  xmlXPathContextPtr ctxt)
1154 1155 1156 1157 1158 1159 1160
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virNodeDeviceObjPtr obj;

    num = virXPathNodeSet("/node/device", ctxt, &nodes);
1161
    if (num < 0)
1162
        goto error;
1163 1164

    for (i = 0; i < num; i++) {
1165
        virNodeDeviceDefPtr def;
C
Cole Robinson 已提交
1166 1167 1168 1169
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                  "nodedev");
        if (!node)
            goto error;
1170

C
Cole Robinson 已提交
1171 1172 1173
        def = virNodeDeviceDefParseNode(ctxt->doc, node, 0, NULL);
        if (!def)
            goto error;
1174

1175
        if (!(obj = virNodeDeviceObjAssignDef(privconn->devs, def))) {
1176 1177 1178
            virNodeDeviceDefFree(def);
            goto error;
        }
1179 1180 1181 1182 1183

        virNodeDeviceObjUnlock(obj);
    }

    ret = 0;
1184
 error:
1185 1186 1187 1188
    VIR_FREE(nodes);
    return ret;
}

1189
static int
1190
testParseAuthUsers(testDriverPtr privconn,
1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223
                   xmlXPathContextPtr ctxt)
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;

    num = virXPathNodeSet("/node/auth/user", ctxt, &nodes);
    if (num < 0)
        goto error;

    privconn->numAuths = num;
    if (num && VIR_ALLOC_N(privconn->auths, num) < 0)
        goto error;

    for (i = 0; i < num; i++) {
        char *username, *password;

        ctxt->node = nodes[i];
        username = virXPathString("string(.)", ctxt);
        if (!username || STREQ(username, "")) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("missing username in /node/auth/user field"));
            VIR_FREE(username);
            goto error;
        }
        /* This field is optional. */
        password = virXMLPropString(nodes[i], "password");

        privconn->auths[i].username = username;
        privconn->auths[i].password = password;
    }

    ret = 0;
1224
 error:
1225 1226 1227
    VIR_FREE(nodes);
    return ret;
}
1228

C
Cole Robinson 已提交
1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259
static int
testOpenParse(testDriverPtr privconn,
              const char *file,
              xmlXPathContextPtr ctxt)
{
    if (!xmlStrEqual(ctxt->node->name, BAD_CAST "node")) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("Root element is not 'node'"));
        goto error;
    }

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

    return 0;
 error:
    return -1;
}

1260 1261
/* No shared state between simultaneous test connections initialized
 * from a file.  */
1262 1263 1264 1265 1266
static int
testOpenFromFile(virConnectPtr conn, const char *file)
{
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
1267
    testDriverPtr privconn;
1268

1269
    if (!(privconn = testDriverNew()))
1270
        return VIR_DRV_OPEN_ERROR;
1271

1272 1273 1274 1275 1276 1277
    testDriverLock(privconn);
    conn->privateData = privconn;

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

1278
    if (!(doc = virXMLParseFileCtxt(file, &ctxt)))
1279 1280 1281 1282 1283
        goto error;

    privconn->numCells = 0;
    memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));

C
Cole Robinson 已提交
1284
    if (testOpenParse(privconn, file, ctxt) < 0)
1285
        goto error;
1286

J
Jim Meyering 已提交
1287
    xmlXPathFreeContext(ctxt);
1288
    xmlFreeDoc(doc);
1289
    testDriverUnlock(privconn);
1290

1291
    return 0;
1292 1293

 error:
J
Jim Meyering 已提交
1294
    xmlXPathFreeContext(ctxt);
1295
    xmlFreeDoc(doc);
1296
    testDriverFree(privconn);
1297
    conn->privateData = NULL;
1298
    return VIR_DRV_OPEN_ERROR;
1299 1300
}

1301 1302 1303 1304 1305 1306 1307
/* Simultaneous test:///default connections should share the same
 * common state (among other things, this allows testing event
 * detection in one connection for an action caused in another).  */
static int
testOpenDefault(virConnectPtr conn)
{
    testDriverPtr privconn = NULL;
1308 1309
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
1310
    size_t i;
1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327

    virMutexLock(&defaultLock);
    if (defaultConnections++) {
        conn->privateData = defaultConn;
        virMutexUnlock(&defaultLock);
        return VIR_DRV_OPEN_SUCCESS;
    }

    if (!(privconn = testDriverNew()))
        goto error;

    conn->privateData = privconn;

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

    /* Numa setup */
    privconn->numCells = 2;
1328 1329 1330 1331
    for (i = 0; i < privconn->numCells; i++) {
        privconn->cells[i].numCpus = 8;
        privconn->cells[i].mem = (i + 1) * 2048 * 1024;
        privconn->cells[i].freeMem = (i + 1) * 1024 * 1024;
1332
    }
1333
    for (i = 0; i < 16; i++) {
1334 1335 1336
        virBitmapPtr siblings = virBitmapNew(16);
        if (!siblings)
            goto error;
1337 1338 1339 1340 1341
        ignore_value(virBitmapSetBit(siblings, i));
        privconn->cells[i / 8].cpus[(i % 8)].id = i;
        privconn->cells[i / 8].cpus[(i % 8)].socket_id = i / 8;
        privconn->cells[i / 8].cpus[(i % 8)].core_id = i % 8;
        privconn->cells[i / 8].cpus[(i % 8)].siblings = siblings;
1342 1343 1344 1345 1346
    }

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

1347 1348
    if (!(doc = virXMLParseStringCtxt(defaultConnXML,
                                      _("(test driver)"), &ctxt)))
1349 1350
        goto error;

1351
    if (testOpenParse(privconn, NULL, ctxt) < 0)
1352 1353 1354 1355
        goto error;

    defaultConn = privconn;

1356 1357
    xmlXPathFreeContext(ctxt);
    xmlFreeDoc(doc);
1358 1359 1360 1361 1362 1363
    virMutexUnlock(&defaultLock);

    return VIR_DRV_OPEN_SUCCESS;

 error:
    testDriverFree(privconn);
1364 1365
    xmlXPathFreeContext(ctxt);
    xmlFreeDoc(doc);
1366 1367 1368 1369 1370 1371
    conn->privateData = NULL;
    defaultConnections--;
    virMutexUnlock(&defaultLock);
    return VIR_DRV_OPEN_ERROR;
}

1372 1373 1374 1375
static int
testConnectAuthenticate(virConnectPtr conn,
                        virConnectAuthPtr auth)
{
1376
    testDriverPtr privconn = conn->privateData;
1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400
    int ret = -1;
    ssize_t i;
    char *username = NULL, *password = NULL;

    if (privconn->numAuths == 0)
        return 0;

    /* Authentication is required because the test XML contains a
     * non-empty <auth/> section.  First we must ask for a username.
     */
    username = virAuthGetUsername(conn, auth, "test", NULL, "localhost"/*?*/);
    if (!username) {
        virReportError(VIR_ERR_AUTH_FAILED, "%s",
                       _("authentication failed when asking for username"));
        goto cleanup;
    }

    /* Does the username exist? */
    for (i = 0; i < privconn->numAuths; ++i) {
        if (STREQ(privconn->auths[i].username, username))
            goto found_user;
    }
    i = -1;

1401
 found_user:
1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420
    /* Even if we didn't find the user, we still ask for a password. */
    if (i == -1 || privconn->auths[i].password != NULL) {
        password = virAuthGetPassword(conn, auth, "test",
                                      username, "localhost");
        if (password == NULL) {
            virReportError(VIR_ERR_AUTH_FAILED, "%s",
                           _("authentication failed when asking for password"));
            goto cleanup;
        }
    }

    if (i == -1 ||
        (password && STRNEQ(privconn->auths[i].password, password))) {
        virReportError(VIR_ERR_AUTH_FAILED, "%s",
                       _("authentication failed, see test XML for the correct username/password"));
        goto cleanup;
    }

    ret = 0;
1421
 cleanup:
1422 1423 1424 1425
    VIR_FREE(username);
    VIR_FREE(password);
    return ret;
}
1426

1427
static virDrvOpenStatus testConnectOpen(virConnectPtr conn,
1428
                                        virConnectAuthPtr auth,
1429
                                        virConfPtr conf ATTRIBUTE_UNUSED,
1430
                                        unsigned int flags)
1431
{
1432
    int ret;
1433

E
Eric Blake 已提交
1434 1435
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

1436
    if (!conn->uri)
1437
        return VIR_DRV_OPEN_DECLINED;
1438

1439
    if (!conn->uri->scheme || STRNEQ(conn->uri->scheme, "test"))
1440
        return VIR_DRV_OPEN_DECLINED;
1441

1442
    /* Remote driver should handle these. */
1443
    if (conn->uri->server)
1444 1445
        return VIR_DRV_OPEN_DECLINED;

1446
    /* From this point on, the connection is for us. */
1447 1448 1449
    if (!conn->uri->path
        || conn->uri->path[0] == '\0'
        || (conn->uri->path[0] == '/' && conn->uri->path[1] == '\0')) {
1450 1451
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("testOpen: supply a path or use test:///default"));
1452 1453
        return VIR_DRV_OPEN_ERROR;
    }
1454

1455
    if (STREQ(conn->uri->path, "/default"))
1456 1457
        ret = testOpenDefault(conn);
    else
1458
        ret = testOpenFromFile(conn,
1459
                               conn->uri->path);
1460

1461 1462 1463
    if (ret != VIR_DRV_OPEN_SUCCESS)
        return ret;

1464 1465 1466 1467
    /* Fake authentication. */
    if (testConnectAuthenticate(conn, auth) < 0)
        return VIR_DRV_OPEN_ERROR;

1468
    return VIR_DRV_OPEN_SUCCESS;
1469 1470
}

1471
static int testConnectClose(virConnectPtr conn)
1472
{
1473
    testDriverPtr privconn = conn->privateData;
1474
    bool dflt = false;
1475

1476 1477
    if (privconn == defaultConn) {
        dflt = true;
1478 1479 1480 1481 1482 1483 1484
        virMutexLock(&defaultLock);
        if (--defaultConnections) {
            virMutexUnlock(&defaultLock);
            return 0;
        }
    }

1485
    testDriverLock(privconn);
1486
    testDriverFree(privconn);
1487 1488 1489

    if (dflt) {
        defaultConn = NULL;
1490
        virMutexUnlock(&defaultLock);
1491 1492
    }

1493
    conn->privateData = NULL;
1494
    return 0;
1495 1496
}

1497 1498
static int testConnectGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
                                 unsigned long *hvVer)
1499
{
1500
    *hvVer = 2;
1501
    return 0;
1502 1503
}

1504 1505 1506 1507 1508 1509
static char *testConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return virGetHostname();
}


1510
static int testConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
1511 1512 1513 1514
{
    return 1;
}

1515
static int testConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
1516 1517 1518 1519
{
    return 0;
}

1520
static int testConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
1521 1522 1523 1524
{
    return 1;
}

1525 1526
static int testConnectGetMaxVcpus(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type ATTRIBUTE_UNUSED)
1527 1528 1529 1530
{
    return 32;
}

1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545
static char *
testConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED,
                       const char **xmlCPUs,
                       unsigned int ncpus,
                       unsigned int flags)
{
    char *cpu;

    virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, NULL);

    cpu = cpuBaselineXML(xmlCPUs, ncpus, NULL, 0, flags);

    return cpu;
}

1546 1547
static int testNodeGetInfo(virConnectPtr conn,
                           virNodeInfoPtr info)
1548
{
1549
    testDriverPtr privconn = conn->privateData;
1550
    testDriverLock(privconn);
1551
    memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo));
1552
    testDriverUnlock(privconn);
1553
    return 0;
1554 1555
}

1556
static char *testConnectGetCapabilities(virConnectPtr conn)
1557
{
1558
    testDriverPtr privconn = conn->privateData;
1559
    char *xml;
1560
    testDriverLock(privconn);
1561
    xml = virCapabilitiesFormatXML(privconn->caps);
1562
    testDriverUnlock(privconn);
1563
    return xml;
1564 1565
}

1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585
static char *
testConnectGetSysinfo(virConnectPtr conn ATTRIBUTE_UNUSED,
                      unsigned int flags)
{
    char *ret;
    const char *sysinfo = "<sysinfo type='smbios'>\n"
           "  <bios>\n"
           "    <entry name='vendor'>LENOVO</entry>\n"
           "    <entry name='version'>G4ETA1WW (2.61 )</entry>\n"
           "    <entry name='date'>05/07/2014</entry>\n"
           "    <entry name='release'>2.61</entry>\n"
           "  </bios>\n"
           "</sysinfo>\n";

    virCheckFlags(0, NULL);

    ignore_value(VIR_STRDUP(ret, sysinfo));
    return ret;
}

1586 1587 1588 1589 1590 1591
static const char *
testConnectGetType(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return "TEST";
}

1592
static int testConnectNumOfDomains(virConnectPtr conn)
1593
{
1594
    testDriverPtr privconn = conn->privateData;
1595
    int count;
1596

1597
    testDriverLock(privconn);
1598
    count = virDomainObjListNumOfDomains(privconn->domains, true, NULL, NULL);
1599
    testDriverUnlock(privconn);
1600

1601
    return count;
1602 1603
}

1604 1605 1606
static int testDomainIsActive(virDomainPtr dom)
{
    virDomainObjPtr obj;
1607
    int ret;
1608

1609 1610
    if (!(obj = testDomObjFromDomain(dom)))
        return -1;
1611

1612 1613
    ret = virDomainObjIsActive(obj);
    virDomainObjEndAPI(&obj);
1614 1615 1616 1617 1618 1619
    return ret;
}

static int testDomainIsPersistent(virDomainPtr dom)
{
    virDomainObjPtr obj;
1620 1621 1622 1623
    int ret;

    if (!(obj = testDomObjFromDomain(dom)))
        return -1;
1624 1625 1626

    ret = obj->persistent;

1627
    virDomainObjEndAPI(&obj);
1628 1629 1630
    return ret;
}

1631 1632 1633 1634 1635
static int testDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
{
    return 0;
}

1636
static virDomainPtr
1637
testDomainCreateXML(virConnectPtr conn, const char *xml,
1638
                      unsigned int flags)
1639
{
1640
    testDriverPtr privconn = conn->privateData;
1641
    virDomainPtr ret = NULL;
1642
    virDomainDefPtr def;
1643
    virDomainObjPtr dom = NULL;
1644
    virObjectEventPtr event = NULL;
1645
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
1646

1647 1648 1649
    virCheckFlags(VIR_DOMAIN_START_VALIDATE, NULL);

    if (flags & VIR_DOMAIN_START_VALIDATE)
1650
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
1651

1652
    testDriverLock(privconn);
1653
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
1654
                                       NULL, parse_flags)) == NULL)
1655
        goto cleanup;
1656

1657
    if (testDomainGenerateIfnames(def) < 0)
1658
        goto cleanup;
1659
    if (!(dom = virDomainObjListAdd(privconn->domains,
1660
                                    def,
1661
                                    privconn->xmlopt,
1662
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
1663 1664
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
1665 1666
        goto cleanup;
    def = NULL;
1667

1668 1669 1670 1671 1672
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_BOOTED) < 0) {
        if (!dom->persistent) {
            virDomainObjListRemove(privconn->domains, dom);
            dom = NULL;
        }
1673
        goto cleanup;
1674
    }
1675

1676
    event = virDomainEventLifecycleNewFromObj(dom,
1677 1678 1679
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);

1680
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
1681

1682
 cleanup:
1683
    if (dom)
1684
        virObjectUnlock(dom);
1685
    testObjectEventQueue(privconn, event);
1686
    virDomainDefFree(def);
1687
    testDriverUnlock(privconn);
1688
    return ret;
1689 1690 1691
}


1692
static virDomainPtr testDomainLookupByID(virConnectPtr conn,
1693
                                         int id)
1694
{
1695
    testDriverPtr privconn = conn->privateData;
1696 1697
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1698

1699
    if (!(dom = virDomainObjListFindByID(privconn->domains, id))) {
1700
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1701
        goto cleanup;
1702 1703
    }

1704
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
1705

1706
 cleanup:
1707
    if (dom)
1708
        virObjectUnlock(dom);
1709
    return ret;
1710 1711
}

1712
static virDomainPtr testDomainLookupByUUID(virConnectPtr conn,
1713
                                           const unsigned char *uuid)
1714
{
1715
    testDriverPtr privconn = conn->privateData;
1716
    virDomainPtr ret = NULL;
1717
    virDomainObjPtr dom;
1718

1719
    if (!(dom = virDomainObjListFindByUUID(privconn->domains, uuid))) {
1720
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1721
        goto cleanup;
1722
    }
1723

1724
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
1725

1726
 cleanup:
1727
    if (dom)
1728
        virObjectUnlock(dom);
1729
    return ret;
1730 1731
}

1732
static virDomainPtr testDomainLookupByName(virConnectPtr conn,
1733
                                           const char *name)
1734
{
1735
    testDriverPtr privconn = conn->privateData;
1736 1737
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1738

1739
    if (!(dom = virDomainObjListFindByName(privconn->domains, name))) {
1740
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1741
        goto cleanup;
1742
    }
1743

1744
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
1745

1746
 cleanup:
1747
    virDomainObjEndAPI(&dom);
1748
    return ret;
1749 1750
}

1751 1752 1753
static int testConnectListDomains(virConnectPtr conn,
                                  int *ids,
                                  int maxids)
1754
{
1755
    testDriverPtr privconn = conn->privateData;
1756

1757 1758
    return virDomainObjListGetActiveIDs(privconn->domains, ids, maxids,
                                        NULL, NULL);
1759 1760
}

1761
static int testDomainDestroy(virDomainPtr domain)
1762
{
1763
    testDriverPtr privconn = domain->conn->privateData;
1764
    virDomainObjPtr privdom;
1765
    virObjectEventPtr event = NULL;
1766
    int ret = -1;
1767

1768
    if (!(privdom = testDomObjFromDomain(domain)))
1769
        goto cleanup;
1770

1771 1772 1773 1774 1775 1776
    if (!virDomainObjIsActive(privdom)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto cleanup;
    }

J
Jiri Denemark 已提交
1777
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_DESTROYED);
1778
    event = virDomainEventLifecycleNewFromObj(privdom,
1779 1780
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
1781

1782 1783
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
1784 1785

    ret = 0;
1786
 cleanup:
1787
    virDomainObjEndAPI(&privdom);
1788
    testObjectEventQueue(privconn, event);
1789
    return ret;
1790 1791
}

1792
static int testDomainResume(virDomainPtr domain)
1793
{
1794
    testDriverPtr privconn = domain->conn->privateData;
1795
    virDomainObjPtr privdom;
1796
    virObjectEventPtr event = NULL;
1797
    int ret = -1;
1798

1799 1800
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1801

J
Jiri Denemark 已提交
1802
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_PAUSED) {
1803 1804
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"),
                       domain->name);
1805
        goto cleanup;
1806
    }
1807

J
Jiri Denemark 已提交
1808 1809
    virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                         VIR_DOMAIN_RUNNING_UNPAUSED);
1810
    event = virDomainEventLifecycleNewFromObj(privdom,
1811 1812
                                     VIR_DOMAIN_EVENT_RESUMED,
                                     VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
1813 1814
    ret = 0;

1815
 cleanup:
1816
    virDomainObjEndAPI(&privdom);
1817
    testObjectEventQueue(privconn, event);
1818
    return ret;
1819 1820
}

1821
static int testDomainSuspend(virDomainPtr domain)
1822
{
1823
    testDriverPtr privconn = domain->conn->privateData;
1824
    virDomainObjPtr privdom;
1825
    virObjectEventPtr event = NULL;
1826
    int ret = -1;
J
Jiri Denemark 已提交
1827
    int state;
1828

1829 1830
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1831

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

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

1845
 cleanup:
1846
    virDomainObjEndAPI(&privdom);
1847
    testObjectEventQueue(privconn, event);
1848
    return ret;
1849 1850
}

1851
static int testDomainShutdownFlags(virDomainPtr domain,
1852
                                   unsigned int flags)
1853
{
1854
    testDriverPtr privconn = domain->conn->privateData;
1855
    virDomainObjPtr privdom;
1856
    virObjectEventPtr event = NULL;
1857
    int ret = -1;
1858

1859 1860
    virCheckFlags(0, -1);

1861

1862
    if (!(privdom = testDomObjFromDomain(domain)))
1863
        goto cleanup;
1864

J
Jiri Denemark 已提交
1865
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
1866 1867
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("domain '%s' not running"), domain->name);
1868
        goto cleanup;
1869
    }
1870

J
Jiri Denemark 已提交
1871
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1872
    event = virDomainEventLifecycleNewFromObj(privdom,
1873 1874
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1875

1876 1877
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
1878

1879
    ret = 0;
1880
 cleanup:
1881
    virDomainObjEndAPI(&privdom);
1882
    testObjectEventQueue(privconn, event);
1883
    return ret;
1884 1885
}

1886
static int testDomainShutdown(virDomainPtr domain)
1887
{
1888
    return testDomainShutdownFlags(domain, 0);
1889 1890
}

1891
/* Similar behaviour as shutdown */
1892
static int testDomainReboot(virDomainPtr domain,
1893
                            unsigned int action ATTRIBUTE_UNUSED)
1894
{
1895
    testDriverPtr privconn = domain->conn->privateData;
1896
    virDomainObjPtr privdom;
1897
    virObjectEventPtr event = NULL;
1898
    int ret = -1;
1899 1900


1901
    if (!(privdom = testDomObjFromDomain(domain)))
1902
        goto cleanup;
1903

1904 1905 1906 1907 1908 1909
    if (!virDomainObjIsActive(privdom)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto cleanup;
    }

J
Jiri Denemark 已提交
1910 1911 1912
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTDOWN,
                         VIR_DOMAIN_SHUTDOWN_USER);

1913 1914
    switch (privdom->def->onReboot) {
    case VIR_DOMAIN_LIFECYCLE_DESTROY:
J
Jiri Denemark 已提交
1915 1916
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1917 1918
        break;

1919
    case VIR_DOMAIN_LIFECYCLE_RESTART:
J
Jiri Denemark 已提交
1920 1921
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
1922 1923
        break;

1924
    case VIR_DOMAIN_LIFECYCLE_PRESERVE:
J
Jiri Denemark 已提交
1925 1926
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1927 1928
        break;

1929
    case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME:
J
Jiri Denemark 已提交
1930 1931
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
1932
        break;
1933

1934
    default:
J
Jiri Denemark 已提交
1935 1936
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1937 1938
        break;
    }
1939

J
Jiri Denemark 已提交
1940 1941
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1942
        event = virDomainEventLifecycleNewFromObj(privdom,
1943 1944
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1945

1946 1947
        if (!privdom->persistent)
            virDomainObjListRemove(privconn->domains, privdom);
1948 1949
    }

1950
    ret = 0;
1951
 cleanup:
1952
    virDomainObjEndAPI(&privdom);
1953
    testObjectEventQueue(privconn, event);
1954
    return ret;
1955 1956
}

1957
static int testDomainGetInfo(virDomainPtr domain,
1958
                             virDomainInfoPtr info)
1959
{
1960
    struct timeval tv;
1961
    virDomainObjPtr privdom;
1962
    int ret = -1;
1963

1964 1965
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1966 1967

    if (gettimeofday(&tv, NULL) < 0) {
1968 1969
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("getting time of day"));
1970
        goto cleanup;
1971 1972
    }

J
Jiri Denemark 已提交
1973
    info->state = virDomainObjGetState(privdom, NULL);
1974
    info->memory = privdom->def->mem.cur_balloon;
1975
    info->maxMem = virDomainDefGetMemoryTotal(privdom->def);
1976
    info->nrVirtCpu = virDomainDefGetVcpus(privdom->def);
1977
    info->cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
1978 1979
    ret = 0;

1980
 cleanup:
1981
    virDomainObjEndAPI(&privdom);
1982
    return ret;
1983 1984
}

1985 1986 1987 1988 1989 1990 1991 1992 1993 1994
static int
testDomainGetState(virDomainPtr domain,
                   int *state,
                   int *reason,
                   unsigned int flags)
{
    virDomainObjPtr privdom;

    virCheckFlags(0, -1);

1995 1996
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1997

J
Jiri Denemark 已提交
1998
    *state = virDomainObjGetState(privdom, reason);
1999

2000
    virDomainObjEndAPI(&privdom);
2001 2002

    return 0;
2003 2004
}

2005 2006
#define TEST_SAVE_MAGIC "TestGuestMagic"

2007 2008 2009
static int
testDomainSaveFlags(virDomainPtr domain, const char *path,
                    const char *dxml, unsigned int flags)
2010
{
2011
    testDriverPtr privconn = domain->conn->privateData;
2012 2013 2014
    char *xml = NULL;
    int fd = -1;
    int len;
2015
    virDomainObjPtr privdom;
2016
    virObjectEventPtr event = NULL;
2017
    int ret = -1;
2018

2019 2020
    virCheckFlags(0, -1);
    if (dxml) {
2021 2022
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
2023 2024 2025
        return -1;
    }

2026

2027
    if (!(privdom = testDomObjFromDomain(domain)))
2028
        goto cleanup;
2029

2030 2031 2032 2033 2034 2035
    if (!virDomainObjIsActive(privdom)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto cleanup;
    }

2036
    xml = virDomainDefFormat(privdom->def, privconn->caps,
2037
                             VIR_DOMAIN_DEF_FORMAT_SECURE);
C
Cole Robinson 已提交
2038

2039
    if (xml == NULL) {
2040
        virReportSystemError(errno,
2041 2042
                             _("saving domain '%s' failed to allocate space for metadata"),
                             domain->name);
2043
        goto cleanup;
2044
    }
2045 2046

    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
2047
        virReportSystemError(errno,
2048 2049
                             _("saving domain '%s' to '%s': open failed"),
                             domain->name, path);
2050
        goto cleanup;
2051
    }
2052
    len = strlen(xml);
2053
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
2054
        virReportSystemError(errno,
2055 2056
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
2057
        goto cleanup;
2058
    }
2059
    if (safewrite(fd, (char*)&len, sizeof(len)) < 0) {
2060
        virReportSystemError(errno,
2061 2062
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
2063
        goto cleanup;
2064
    }
2065
    if (safewrite(fd, xml, len) < 0) {
2066
        virReportSystemError(errno,
2067 2068
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
2069
        goto cleanup;
2070
    }
2071

2072
    if (VIR_CLOSE(fd) < 0) {
2073
        virReportSystemError(errno,
2074 2075
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
2076
        goto cleanup;
2077
    }
2078 2079
    fd = -1;

J
Jiri Denemark 已提交
2080
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SAVED);
2081
    event = virDomainEventLifecycleNewFromObj(privdom,
2082 2083
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
2084

2085 2086
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
2087

2088
    ret = 0;
2089
 cleanup:
2090 2091 2092 2093
    VIR_FREE(xml);

    /* Don't report failure in close or unlink, because
     * in either case we're already in a failure scenario
Y
Yuri Chornoivan 已提交
2094
     * and have reported an earlier error */
2095
    if (ret != 0) {
2096
        VIR_FORCE_CLOSE(fd);
2097 2098
        unlink(path);
    }
2099
    virDomainObjEndAPI(&privdom);
2100
    testObjectEventQueue(privconn, event);
2101
    return ret;
2102 2103
}

2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115
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)
2116
{
2117
    testDriverPtr privconn = conn->privateData;
2118
    char *xml = NULL;
2119
    char magic[15];
2120 2121 2122
    int fd = -1;
    int len;
    virDomainDefPtr def = NULL;
2123
    virDomainObjPtr dom = NULL;
2124
    virObjectEventPtr event = NULL;
2125
    int ret = -1;
2126

2127 2128
    virCheckFlags(0, -1);
    if (dxml) {
2129 2130
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
2131 2132 2133
        return -1;
    }

2134
    if ((fd = open(path, O_RDONLY)) < 0) {
2135
        virReportSystemError(errno,
2136 2137
                             _("cannot read domain image '%s'"),
                             path);
2138
        goto cleanup;
2139
    }
2140
    if (saferead(fd, magic, sizeof(magic)) != sizeof(magic)) {
2141
        virReportSystemError(errno,
2142 2143
                             _("incomplete save header in '%s'"),
                             path);
2144
        goto cleanup;
2145
    }
2146
    if (memcmp(magic, TEST_SAVE_MAGIC, sizeof(magic))) {
2147 2148
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("mismatched header magic"));
2149
        goto cleanup;
2150
    }
2151
    if (saferead(fd, (char*)&len, sizeof(len)) != sizeof(len)) {
2152
        virReportSystemError(errno,
2153 2154
                             _("failed to read metadata length in '%s'"),
                             path);
2155
        goto cleanup;
2156 2157
    }
    if (len < 1 || len > 8192) {
2158 2159
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("length of metadata out of range"));
2160
        goto cleanup;
2161
    }
2162
    if (VIR_ALLOC_N(xml, len+1) < 0)
2163
        goto cleanup;
2164
    if (saferead(fd, xml, len) != len) {
2165
        virReportSystemError(errno,
2166
                             _("incomplete metadata in '%s'"), path);
2167
        goto cleanup;
2168 2169
    }
    xml[len] = '\0';
2170

2171
    def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
2172
                                  NULL, VIR_DOMAIN_DEF_PARSE_INACTIVE);
2173
    if (!def)
2174
        goto cleanup;
2175

2176
    if (testDomainGenerateIfnames(def) < 0)
2177
        goto cleanup;
2178
    if (!(dom = virDomainObjListAdd(privconn->domains,
2179
                                    def,
2180
                                    privconn->xmlopt,
2181 2182 2183
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
2184 2185
        goto cleanup;
    def = NULL;
2186

2187 2188 2189 2190 2191
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_RESTORED) < 0) {
        if (!dom->persistent) {
            virDomainObjListRemove(privconn->domains, dom);
            dom = NULL;
        }
2192
        goto cleanup;
2193
    }
2194

2195
    event = virDomainEventLifecycleNewFromObj(dom,
2196 2197
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
2198
    ret = 0;
2199

2200
 cleanup:
2201 2202
    virDomainDefFree(def);
    VIR_FREE(xml);
2203
    VIR_FORCE_CLOSE(fd);
2204
    if (dom)
2205
        virObjectUnlock(dom);
2206
    testObjectEventQueue(privconn, event);
2207
    return ret;
2208 2209
}

2210 2211 2212 2213 2214 2215 2216
static int
testDomainRestore(virConnectPtr conn,
                  const char *path)
{
    return testDomainRestoreFlags(conn, path, NULL, 0);
}

2217 2218 2219 2220
static int testDomainCoreDumpWithFormat(virDomainPtr domain,
                                        const char *to,
                                        unsigned int dumpformat,
                                        unsigned int flags)
2221
{
2222
    testDriverPtr privconn = domain->conn->privateData;
2223
    int fd = -1;
2224
    virDomainObjPtr privdom;
2225
    virObjectEventPtr event = NULL;
2226
    int ret = -1;
2227

E
Eric Blake 已提交
2228 2229
    virCheckFlags(VIR_DUMP_CRASH, -1);

2230

2231
    if (!(privdom = testDomObjFromDomain(domain)))
2232
        goto cleanup;
2233

2234 2235 2236 2237 2238 2239
    if (!virDomainObjIsActive(privdom)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto cleanup;
    }

2240
    if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
2241
        virReportSystemError(errno,
2242 2243
                             _("domain '%s' coredump: failed to open %s"),
                             domain->name, to);
2244
        goto cleanup;
2245
    }
2246
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
2247
        virReportSystemError(errno,
2248 2249
                             _("domain '%s' coredump: failed to write header to %s"),
                             domain->name, to);
2250
        goto cleanup;
2251
    }
2252
    if (VIR_CLOSE(fd) < 0) {
2253
        virReportSystemError(errno,
2254 2255
                             _("domain '%s' coredump: write failed: %s"),
                             domain->name, to);
2256
        goto cleanup;
2257
    }
2258

2259 2260 2261 2262 2263 2264 2265
    /* we don't support non-raw formats in test driver */
    if (dumpformat != VIR_DOMAIN_CORE_DUMP_FORMAT_RAW) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("kdump-compressed format is not supported here"));
        goto cleanup;
    }

2266
    if (flags & VIR_DUMP_CRASH) {
J
Jiri Denemark 已提交
2267
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_CRASHED);
2268
        event = virDomainEventLifecycleNewFromObj(privdom,
2269 2270
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
2271 2272
        if (!privdom->persistent)
            virDomainObjListRemove(privconn->domains, privdom);
2273
    }
2274

2275
    ret = 0;
2276
 cleanup:
2277
    VIR_FORCE_CLOSE(fd);
2278
    virDomainObjEndAPI(&privdom);
2279
    testObjectEventQueue(privconn, event);
2280
    return ret;
2281 2282
}

2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296

static int
testDomainCoreDump(virDomainPtr domain,
                   const char *to,
                   unsigned int flags)
{
    return testDomainCoreDumpWithFormat(domain, to,
                                        VIR_DOMAIN_CORE_DUMP_FORMAT_RAW, flags);
}


static char *
testDomainGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED)
{
2297 2298 2299
    char *ret;

    ignore_value(VIR_STRDUP(ret, "linux"));
2300
    return ret;
2301 2302
}

2303 2304 2305

static unsigned long long
testDomainGetMaxMemory(virDomainPtr domain)
2306
{
2307
    virDomainObjPtr privdom;
2308
    unsigned long long ret = 0;
2309

2310 2311
    if (!(privdom = testDomObjFromDomain(domain)))
        return 0;
2312

2313
    ret = virDomainDefGetMemoryTotal(privdom->def);
2314

2315
    virDomainObjEndAPI(&privdom);
2316
    return ret;
2317 2318
}

2319 2320
static int testDomainSetMaxMemory(virDomainPtr domain,
                                  unsigned long memory)
2321
{
2322 2323
    virDomainObjPtr privdom;

2324 2325
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2326 2327

    /* XXX validate not over host memory wrt to other domains */
2328
    virDomainDefSetMemoryTotal(privdom->def, memory);
2329

2330
    virDomainObjEndAPI(&privdom);
2331
    return 0;
2332 2333
}

2334 2335
static int testDomainSetMemory(virDomainPtr domain,
                               unsigned long memory)
2336
{
2337
    virDomainObjPtr privdom;
2338
    int ret = -1;
2339

2340 2341
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2342

2343
    if (memory > virDomainDefGetMemoryTotal(privdom->def)) {
2344
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2345
        goto cleanup;
2346
    }
2347

2348
    privdom->def->mem.cur_balloon = memory;
2349 2350
    ret = 0;

2351
 cleanup:
2352
    virDomainObjEndAPI(&privdom);
2353
    return ret;
2354 2355
}

2356 2357
static int
testDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
C
Cole Robinson 已提交
2358
{
2359 2360 2361 2362
    virDomainObjPtr vm;
    virDomainDefPtr def;
    int ret = -1;

2363 2364
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2365 2366
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

2367 2368
    if (!(vm = testDomObjFromDomain(domain)))
        return -1;
2369

2370
    if (!(def = virDomainObjGetOneDef(vm, flags)))
2371
        goto cleanup;
2372

2373 2374 2375
    if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
        ret = virDomainDefGetVcpusMax(def);
    else
2376
        ret = virDomainDefGetVcpus(def);
2377

2378
 cleanup:
2379
    virDomainObjEndAPI(&vm);
2380
    return ret;
C
Cole Robinson 已提交
2381 2382
}

2383 2384 2385
static int
testDomainGetMaxVcpus(virDomainPtr domain)
{
2386
    return testDomainGetVcpusFlags(domain, (VIR_DOMAIN_AFFECT_LIVE |
2387 2388 2389 2390 2391 2392 2393
                                            VIR_DOMAIN_VCPU_MAXIMUM));
}

static int
testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
                        unsigned int flags)
{
2394
    testDriverPtr driver = domain->conn->privateData;
2395
    virDomainObjPtr privdom = NULL;
2396
    virDomainDefPtr def;
2397
    virDomainDefPtr persistentDef;
C
Cole Robinson 已提交
2398 2399
    int ret = -1, maxvcpus;

2400 2401
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2402 2403
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

2404
    if ((maxvcpus = testConnectGetMaxVcpus(domain->conn, NULL)) < 0)
2405
        return -1;
2406 2407

    if (nrCpus > maxvcpus) {
2408
        virReportError(VIR_ERR_INVALID_ARG,
2409 2410
                       _("requested cpu amount exceeds maximum supported amount "
                         "(%d > %d)"), nrCpus, maxvcpus);
2411 2412
        return -1;
    }
2413

2414 2415
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2416

2417
    if (virDomainObjGetDefs(privdom, flags, &def, &persistentDef) < 0)
C
Cole Robinson 已提交
2418 2419
        goto cleanup;

2420
    if (def && virDomainDefGetVcpusMax(def) < nrCpus) {
2421 2422
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested cpu amount exceeds maximum (%d > %d)"),
2423
                       nrCpus, virDomainDefGetVcpusMax(def));
2424
        goto cleanup;
2425
    }
2426

2427 2428
    if (persistentDef &&
        !(flags & VIR_DOMAIN_VCPU_MAXIMUM) &&
2429
        virDomainDefGetVcpusMax(persistentDef) < nrCpus) {
2430 2431
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested cpu amount exceeds maximum (%d > %d)"),
2432
                       nrCpus, virDomainDefGetVcpusMax(persistentDef));
2433
        goto cleanup;
2434
    }
2435

2436 2437 2438
    if (def &&
        virDomainDefSetVcpus(def, nrCpus) < 0)
        goto cleanup;
2439

2440 2441
    if (persistentDef) {
        if (flags & VIR_DOMAIN_VCPU_MAXIMUM) {
2442 2443
            if (virDomainDefSetVcpusMax(persistentDef, nrCpus,
                                        driver->xmlopt) < 0)
2444
                goto cleanup;
2445
        } else {
2446 2447
            if (virDomainDefSetVcpus(persistentDef, nrCpus) < 0)
                goto cleanup;
2448
        }
2449
    }
2450

2451 2452
    ret = 0;

2453
 cleanup:
2454
    virDomainObjEndAPI(&privdom);
2455
    return ret;
2456 2457
}

2458
static int
2459
testDomainSetVcpus(virDomainPtr domain, unsigned int nrCpus)
2460
{
2461
    return testDomainSetVcpusFlags(domain, nrCpus, VIR_DOMAIN_AFFECT_LIVE);
2462 2463
}

C
Cole Robinson 已提交
2464 2465 2466 2467 2468 2469
static int testDomainGetVcpus(virDomainPtr domain,
                              virVcpuInfoPtr info,
                              int maxinfo,
                              unsigned char *cpumaps,
                              int maplen)
{
2470
    testDriverPtr privconn = domain->conn->privateData;
C
Cole Robinson 已提交
2471
    virDomainObjPtr privdom;
2472
    virDomainDefPtr def;
2473
    size_t i;
2474
    int hostcpus;
C
Cole Robinson 已提交
2475 2476 2477
    int ret = -1;
    struct timeval tv;
    unsigned long long statbase;
2478
    virBitmapPtr allcpumap = NULL;
C
Cole Robinson 已提交
2479

2480 2481
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
C
Cole Robinson 已提交
2482 2483

    if (!virDomainObjIsActive(privdom)) {
2484
        virReportError(VIR_ERR_OPERATION_INVALID,
2485
                       "%s", _("cannot list vcpus for an inactive domain"));
C
Cole Robinson 已提交
2486 2487 2488
        goto cleanup;
    }

2489
    def = privdom->def;
C
Cole Robinson 已提交
2490 2491

    if (gettimeofday(&tv, NULL) < 0) {
2492
        virReportSystemError(errno,
C
Cole Robinson 已提交
2493 2494 2495 2496 2497 2498 2499
                             "%s", _("getting time of day"));
        goto cleanup;
    }

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

    hostcpus = VIR_NODEINFO_MAXCPUS(privconn->nodeInfo);
2500 2501 2502 2503 2504
    if (!(allcpumap = virBitmapNew(hostcpus)))
        goto cleanup;

    virBitmapSetAll(allcpumap);

C
Cole Robinson 已提交
2505
    /* Clamp to actual number of vcpus */
2506 2507
    if (maxinfo > virDomainDefGetVcpus(privdom->def))
        maxinfo = virDomainDefGetVcpus(privdom->def);
C
Cole Robinson 已提交
2508

2509 2510
    memset(info, 0, sizeof(*info) * maxinfo);
    memset(cpumaps, 0, maxinfo * maplen);
C
Cole Robinson 已提交
2511

2512
    for (i = 0; i < maxinfo; i++) {
2513
        virDomainVcpuDefPtr vcpu = virDomainDefGetVcpu(def, i);
2514
        virBitmapPtr bitmap = NULL;
C
Cole Robinson 已提交
2515

2516 2517
        if (!vcpu->online)
            continue;
C
Cole Robinson 已提交
2518

2519 2520
        if (vcpu->cpumask)
            bitmap = vcpu->cpumask;
2521 2522 2523 2524
        else if (def->cpumask)
            bitmap = def->cpumask;
        else
            bitmap = allcpumap;
C
Cole Robinson 已提交
2525

2526 2527
        if (cpumaps)
            virBitmapToDataBuf(bitmap, VIR_GET_CPUMAP(cpumaps, maplen, i), maplen);
C
Cole Robinson 已提交
2528

2529 2530 2531
        info[i].number = i;
        info[i].state = VIR_VCPU_RUNNING;
        info[i].cpu = virBitmapLastSetBit(bitmap);
C
Cole Robinson 已提交
2532

2533 2534
        /* Fake an increasing cpu time value */
        info[i].cpuTime = statbase / 10;
C
Cole Robinson 已提交
2535 2536 2537
    }

    ret = maxinfo;
2538
 cleanup:
2539
    virBitmapFree(allcpumap);
2540
    virDomainObjEndAPI(&privdom);
C
Cole Robinson 已提交
2541 2542 2543
    return ret;
}

C
Cole Robinson 已提交
2544 2545 2546 2547 2548
static int testDomainPinVcpu(virDomainPtr domain,
                             unsigned int vcpu,
                             unsigned char *cpumap,
                             int maplen)
{
2549
    virDomainVcpuDefPtr vcpuinfo;
C
Cole Robinson 已提交
2550
    virDomainObjPtr privdom;
2551
    virDomainDefPtr def;
C
Cole Robinson 已提交
2552 2553
    int ret = -1;

2554 2555
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
C
Cole Robinson 已提交
2556

2557 2558
    def = privdom->def;

C
Cole Robinson 已提交
2559
    if (!virDomainObjIsActive(privdom)) {
2560
        virReportError(VIR_ERR_OPERATION_INVALID,
2561
                       "%s", _("cannot pin vcpus on an inactive domain"));
C
Cole Robinson 已提交
2562 2563 2564
        goto cleanup;
    }

2565 2566
    if (!(vcpuinfo = virDomainDefGetVcpu(def, vcpu)) ||
        !vcpuinfo->online) {
2567 2568 2569
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested vcpu '%d' is not present in the domain"),
                       vcpu);
C
Cole Robinson 已提交
2570 2571 2572
        goto cleanup;
    }

2573 2574 2575
    virBitmapFree(vcpuinfo->cpumask);

    if (!(vcpuinfo->cpumask = virBitmapNewData(cpumap, maplen)))
2576
        goto cleanup;
C
Cole Robinson 已提交
2577 2578

    ret = 0;
2579

2580
 cleanup:
2581
    virDomainObjEndAPI(&privdom);
C
Cole Robinson 已提交
2582 2583 2584
    return ret;
}

2585 2586 2587 2588 2589 2590 2591
static int
testDomainGetVcpuPinInfo(virDomainPtr dom,
                        int ncpumaps,
                        unsigned char *cpumaps,
                        int maplen,
                        unsigned int flags)
{
2592
    testDriverPtr driver = dom->conn->privateData;
2593 2594
    virDomainObjPtr privdom;
    virDomainDefPtr def;
2595
    int ret = -1;
2596 2597 2598 2599 2600 2601 2602

    if (!(privdom = testDomObjFromDomain(dom)))
        return -1;

    if (!(def = virDomainObjGetOneDef(privdom, flags)))
        goto cleanup;

2603 2604 2605
    ret = virDomainDefGetVcpuPinInfoHelper(def, maplen, ncpumaps, cpumaps,
                                           VIR_NODEINFO_MAXCPUS(driver->nodeInfo),
                                           NULL);
2606 2607 2608 2609 2610 2611

 cleanup:
    virDomainObjEndAPI(&privdom);
    return ret;
}

2612
static char *testDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
2613
{
2614
    testDriverPtr privconn = domain->conn->privateData;
2615
    virDomainDefPtr def;
2616
    virDomainObjPtr privdom;
2617 2618
    char *ret = NULL;

2619 2620
    /* Flags checked by virDomainDefFormat */

2621 2622
    if (!(privdom = testDomObjFromDomain(domain)))
        return NULL;
2623

2624 2625
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
2626

2627 2628
    ret = virDomainDefFormat(def, privconn->caps,
                             virDomainDefFormatConvertXMLFlags(flags));
2629

2630
    virDomainObjEndAPI(&privdom);
2631
    return ret;
2632
}
2633

2634 2635
static int testConnectNumOfDefinedDomains(virConnectPtr conn)
{
2636
    testDriverPtr privconn = conn->privateData;
2637

2638
    return virDomainObjListNumOfDomains(privconn->domains, false, NULL, NULL);
2639 2640
}

2641 2642
static int testConnectListDefinedDomains(virConnectPtr conn,
                                         char **const names,
2643 2644
                                         int maxnames)
{
2645

2646
    testDriverPtr privconn = conn->privateData;
2647 2648

    memset(names, 0, sizeof(*names)*maxnames);
2649 2650
    return virDomainObjListGetInactiveNames(privconn->domains, names, maxnames,
                                            NULL, NULL);
2651 2652
}

2653 2654 2655
static virDomainPtr testDomainDefineXMLFlags(virConnectPtr conn,
                                             const char *xml,
                                             unsigned int flags)
2656
{
2657
    testDriverPtr privconn = conn->privateData;
2658
    virDomainPtr ret = NULL;
2659
    virDomainDefPtr def;
2660
    virDomainObjPtr dom = NULL;
2661
    virObjectEventPtr event = NULL;
2662
    virDomainDefPtr oldDef = NULL;
2663 2664 2665
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;

    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
2666

2667
    if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
2668
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
2669

2670
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
2671
                                       NULL, parse_flags)) == NULL)
2672
        goto cleanup;
2673

2674 2675 2676
    if (virXMLCheckIllegalChars("name", def->name, "\n") < 0)
        goto cleanup;

2677
    if (testDomainGenerateIfnames(def) < 0)
2678
        goto cleanup;
2679
    if (!(dom = virDomainObjListAdd(privconn->domains,
2680
                                    def,
2681
                                    privconn->xmlopt,
2682 2683
                                    0,
                                    &oldDef)))
2684
        goto cleanup;
2685
    def = NULL;
2686
    dom->persistent = 1;
2687

2688
    event = virDomainEventLifecycleNewFromObj(dom,
2689
                                     VIR_DOMAIN_EVENT_DEFINED,
2690
                                     !oldDef ?
2691 2692
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
2693

2694
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
2695

2696
 cleanup:
2697
    virDomainDefFree(def);
2698
    virDomainDefFree(oldDef);
2699
    if (dom)
2700
        virObjectUnlock(dom);
2701
    testObjectEventQueue(privconn, event);
2702
    return ret;
2703 2704
}

2705 2706 2707 2708 2709 2710
static virDomainPtr
testDomainDefineXML(virConnectPtr conn, const char *xml)
{
    return testDomainDefineXMLFlags(conn, xml, 0);
}

2711 2712 2713 2714 2715 2716
static char *testDomainGetMetadata(virDomainPtr dom,
                                   int type,
                                   const char *uri,
                                   unsigned int flags)
{
    virDomainObjPtr privdom;
2717
    char *ret;
2718 2719 2720 2721

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, NULL);

2722 2723
    if (!(privdom = testDomObjFromDomain(dom)))
        return NULL;
2724

2725
    ret = virDomainObjGetMetadata(privdom, type, uri, flags);
2726

2727
    virDomainObjEndAPI(&privdom);
2728 2729 2730 2731 2732 2733 2734 2735 2736 2737
    return ret;
}

static int testDomainSetMetadata(virDomainPtr dom,
                                 int type,
                                 const char *metadata,
                                 const char *key,
                                 const char *uri,
                                 unsigned int flags)
{
2738
    testDriverPtr privconn = dom->conn->privateData;
2739
    virDomainObjPtr privdom;
2740
    int ret;
2741 2742 2743 2744

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

2745 2746
    if (!(privdom = testDomObjFromDomain(dom)))
        return -1;
2747 2748 2749

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

2752 2753 2754 2755 2756 2757
    if (ret == 0) {
        virObjectEventPtr ev = NULL;
        ev = virDomainEventMetadataChangeNewFromObj(privdom, type, uri);
        testObjectEventQueue(privconn, ev);
    }

2758
    virDomainObjEndAPI(&privdom);
2759 2760 2761 2762
    return ret;
}


2763 2764
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
2765 2766
                                      int startCell, int maxCells)
{
2767
    testDriverPtr privconn = conn->privateData;
2768 2769
    int cell;
    size_t i;
2770
    int ret = -1;
2771

2772
    testDriverLock(privconn);
2773
    if (startCell >= privconn->numCells) {
2774 2775
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("Range exceeds available cells"));
2776
        goto cleanup;
2777 2778
    }

2779 2780 2781 2782
    for (cell = startCell, i = 0;
         (cell < privconn->numCells && i < maxCells);
         ++cell, ++i) {
        freemems[i] = privconn->cells[cell].mem;
2783
    }
2784
    ret = i;
2785

2786
 cleanup:
2787
    testDriverUnlock(privconn);
2788
    return ret;
2789 2790
}

2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836
#define TEST_NB_CPU_STATS 4

static int
testNodeGetCPUStats(virConnectPtr conn ATTRIBUTE_UNUSED,
                    int cpuNum ATTRIBUTE_UNUSED,
                    virNodeCPUStatsPtr params,
                    int *nparams,
                    unsigned int flags)
{
    size_t i = 0;

    virCheckFlags(0, -1);

    if (params == NULL) {
        *nparams = TEST_NB_CPU_STATS;
        return 0;
    }

    for (i = 0; i < *nparams && i < 4; i++) {
        switch (i) {
        case 0:
            if (virHostCPUStatsAssign(&params[i],
                                      VIR_NODE_CPU_STATS_USER, 9797400000) < 0)
                return -1;
            break;
        case 1:
            if (virHostCPUStatsAssign(&params[i],
                                      VIR_NODE_CPU_STATS_KERNEL, 34678723400000) < 0)
                return -1;
            break;
        case 2:
            if (virHostCPUStatsAssign(&params[i],
                                      VIR_NODE_CPU_STATS_IDLE, 87264900000) < 0)
                return -1;
            break;
        case 3:
            if (virHostCPUStatsAssign(&params[i],
                                      VIR_NODE_CPU_STATS_IOWAIT, 763600000) < 0)
                return -1;
            break;
        }
    }

    *nparams = i;
    return 0;
}
2837

2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853
static unsigned long long
testNodeGetFreeMemory(virConnectPtr conn)
{
    testDriverPtr privconn = conn->privateData;
    unsigned int freeMem = 0;
    size_t i;

    testDriverLock(privconn);

    for (i = 0; i < privconn->numCells; i++)
        freeMem += privconn->cells[i].freeMem;

    testDriverUnlock(privconn);
    return freeMem;
}

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 int
testNodeGetFreePages(virConnectPtr conn ATTRIBUTE_UNUSED,
                     unsigned int npages,
                     unsigned int *pages ATTRIBUTE_UNUSED,
                     int startCell ATTRIBUTE_UNUSED,
                     unsigned int cellCount,
                     unsigned long long *counts,
                     unsigned int flags)
{
    size_t i = 0, j = 0;
    int x = 6;

    virCheckFlags(0, -1);

    for (i = 0; i < cellCount; i++) {
        for (j = 0; j < npages; j++) {
            x = x * 2 + 7;
            counts[(i * npages) +  j] = x;
        }
    }

    return 0;
}

2878 2879
static int testDomainCreateWithFlags(virDomainPtr domain, unsigned int flags)
{
2880
    testDriverPtr privconn = domain->conn->privateData;
2881
    virDomainObjPtr privdom;
2882
    virObjectEventPtr event = NULL;
2883
    int ret = -1;
2884

2885 2886
    virCheckFlags(0, -1);

2887
    testDriverLock(privconn);
2888

2889
    if (!(privdom = testDomObjFromDomain(domain)))
2890
        goto cleanup;
2891

J
Jiri Denemark 已提交
2892
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_SHUTOFF) {
2893 2894
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Domain '%s' is already running"), domain->name);
2895
        goto cleanup;
2896 2897
    }

2898
    if (testDomainStartState(privconn, privdom,
J
Jiri Denemark 已提交
2899
                             VIR_DOMAIN_RUNNING_BOOTED) < 0)
2900 2901 2902
        goto cleanup;
    domain->id = privdom->def->id;

2903
    event = virDomainEventLifecycleNewFromObj(privdom,
2904 2905
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
2906
    ret = 0;
2907

2908
 cleanup:
2909
    virDomainObjEndAPI(&privdom);
2910
    testObjectEventQueue(privconn, event);
2911
    testDriverUnlock(privconn);
2912
    return ret;
2913 2914
}

2915 2916
static int testDomainCreate(virDomainPtr domain)
{
2917 2918 2919
    return testDomainCreateWithFlags(domain, 0);
}

2920 2921 2922
static int testDomainUndefineFlags(virDomainPtr domain,
                                   unsigned int flags)
{
2923
    testDriverPtr privconn = domain->conn->privateData;
2924
    virDomainObjPtr privdom;
2925
    virObjectEventPtr event = NULL;
2926
    int nsnapshots;
2927
    int ret = -1;
2928

2929 2930
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
                  VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
2931

2932

2933
    if (!(privdom = testDomObjFromDomain(domain)))
2934
        goto cleanup;
2935

C
Cole Robinson 已提交
2936 2937 2938 2939 2940 2941 2942 2943
    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;
    }

2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961
    /* 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. */
    }

2962
    event = virDomainEventLifecycleNewFromObj(privdom,
2963 2964
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
C
Cole Robinson 已提交
2965 2966
    privdom->hasManagedSave = false;

2967
    if (virDomainObjIsActive(privdom))
2968
        privdom->persistent = 0;
2969 2970
    else
        virDomainObjListRemove(privconn->domains, privdom);
2971

2972
    ret = 0;
2973

2974
 cleanup:
2975
    virDomainObjEndAPI(&privdom);
2976
    testObjectEventQueue(privconn, event);
2977
    return ret;
2978 2979
}

2980 2981 2982 2983 2984
static int testDomainUndefine(virDomainPtr domain)
{
    return testDomainUndefineFlags(domain, 0);
}

2985 2986 2987
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
2988 2989
    virDomainObjPtr privdom;

2990 2991
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2992

2993
    *autostart = privdom->autostart;
2994

2995
    virDomainObjEndAPI(&privdom);
2996
    return 0;
2997 2998 2999 3000 3001 3002
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
3003 3004
    virDomainObjPtr privdom;

3005 3006
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3007

3008
    privdom->autostart = autostart ? 1 : 0;
3009

3010
    virDomainObjEndAPI(&privdom);
3011
    return 0;
3012
}
3013

3014
static char *testDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED,
3015 3016
                                        int *nparams)
{
3017 3018
    char *type = NULL;

3019 3020 3021
    if (nparams)
        *nparams = 1;

3022
    ignore_value(VIR_STRDUP(type, "fair"));
3023

3024 3025 3026
    return type;
}

3027
static int
3028 3029 3030 3031
testDomainGetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int *nparams,
                                      unsigned int flags)
3032
{
3033
    virDomainObjPtr privdom;
3034
    int ret = -1;
3035

3036 3037
    virCheckFlags(0, -1);

3038 3039
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3040

3041 3042
    if (virTypedParameterAssign(params, VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, 50) < 0)
3043
        goto cleanup;
3044 3045
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
3046 3047

    *nparams = 1;
3048 3049
    ret = 0;

3050
 cleanup:
3051
    virDomainObjEndAPI(&privdom);
3052
    return ret;
3053
}
3054

3055
static int
3056 3057 3058
testDomainGetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int *nparams)
3059
{
3060
    return testDomainGetSchedulerParametersFlags(domain, params, nparams, 0);
3061
}
3062

3063
static int
3064 3065 3066 3067
testDomainSetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int nparams,
                                      unsigned int flags)
3068
{
3069
    virDomainObjPtr privdom;
3070 3071
    int ret = -1;
    size_t i;
3072

3073
    virCheckFlags(0, -1);
3074 3075 3076 3077
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
3078
        return -1;
3079

3080 3081
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3082

3083
    for (i = 0; i < nparams; i++) {
3084 3085 3086
        if (STREQ(params[i].field, VIR_DOMAIN_SCHEDULER_WEIGHT)) {
            /* XXX */
            /*privdom->weight = params[i].value.ui;*/
3087
        }
3088
    }
3089

3090 3091
    ret = 0;

3092
    virDomainObjEndAPI(&privdom);
3093
    return ret;
3094 3095
}

3096
static int
3097 3098 3099
testDomainSetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int nparams)
3100
{
3101
    return testDomainSetSchedulerParametersFlags(domain, params, nparams, 0);
3102 3103
}

3104 3105
static int testDomainBlockStats(virDomainPtr domain,
                                const char *path,
3106
                                virDomainBlockStatsPtr stats)
3107 3108 3109 3110
{
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
3111
    int ret = -1;
3112

3113 3114 3115 3116 3117 3118
    if (!*path) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("summary statistics are not supported yet"));
        return ret;
    }

3119 3120
    if (!(privdom = testDomObjFromDomain(domain)))
        return ret;
3121

3122 3123 3124 3125 3126 3127
    if (!virDomainObjIsActive(privdom)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto error;
    }

3128
    if (virDomainDiskIndexByName(privdom->def, path, false) < 0) {
3129 3130
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path: %s"), path);
3131 3132 3133 3134
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
3135
        virReportSystemError(errno,
3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148
                             "%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;
3149
 error:
3150
    virDomainObjEndAPI(&privdom);
3151 3152 3153 3154 3155
    return ret;
}

static int testDomainInterfaceStats(virDomainPtr domain,
                                    const char *path,
3156
                                    virDomainInterfaceStatsPtr stats)
3157 3158 3159 3160
{
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
3161 3162
    size_t i;
    int found = 0, ret = -1;
3163

3164 3165
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3166

3167 3168 3169 3170 3171 3172
    if (!virDomainObjIsActive(privdom)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto error;
    }

3173
    for (i = 0; i < privdom->def->nnets; i++) {
3174
        if (privdom->def->nets[i]->ifname &&
3175
            STREQ(privdom->def->nets[i]->ifname, path)) {
3176 3177 3178 3179 3180 3181
            found = 1;
            break;
        }
    }

    if (!found) {
3182 3183
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path, '%s' is not a known interface"), path);
3184 3185 3186 3187
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
3188
        virReportSystemError(errno,
3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204
                             "%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;
3205
 error:
3206
    virDomainObjEndAPI(&privdom);
3207 3208 3209
    return ret;
}

3210

3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228
static virNetworkObjPtr
testNetworkObjFindByUUID(testDriverPtr privconn,
                         const unsigned char *uuid)
{
    virNetworkObjPtr net;
    char uuidstr[VIR_UUID_STRING_BUFLEN];

    if (!(net = virNetworkObjFindByUUID(privconn->networks, uuid))) {
        virUUIDFormat(uuid, uuidstr);
        virReportError(VIR_ERR_NO_NETWORK,
                       _("no network with matching uuid '%s'"),
                       uuidstr);
    }

    return net;
}


3229 3230 3231
static virNetworkPtr
testNetworkLookupByUUID(virConnectPtr conn,
                        const unsigned char *uuid)
3232
{
3233
    testDriverPtr privconn = conn->privateData;
3234
    virNetworkObjPtr net;
3235
    virNetworkPtr ret = NULL;
3236

3237
    if (!(net = testNetworkObjFindByUUID(privconn, uuid)))
3238
        goto cleanup;
3239

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

3242
 cleanup:
3243
    virNetworkObjEndAPI(&net);
3244
    return ret;
3245
}
3246

3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262

static virNetworkObjPtr
testNetworkObjFindByName(testDriverPtr privconn,
                         const char *name)
{
    virNetworkObjPtr net;

    if (!(net = virNetworkObjFindByName(privconn->networks, name)))
        virReportError(VIR_ERR_NO_NETWORK,
                       _("no network with matching name '%s'"),
                       name);

    return net;
}


3263 3264 3265
static virNetworkPtr
testNetworkLookupByName(virConnectPtr conn,
                        const char *name)
3266
{
3267
    testDriverPtr privconn = conn->privateData;
3268 3269
    virNetworkObjPtr net;
    virNetworkPtr ret = NULL;
3270

3271
    if (!(net = testNetworkObjFindByName(privconn, name)))
3272
        goto cleanup;
3273

3274 3275
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

3276
 cleanup:
3277
    virNetworkObjEndAPI(&net);
3278
    return ret;
3279 3280 3281
}


3282 3283
static int
testConnectNumOfNetworks(virConnectPtr conn)
3284
{
3285
    testDriverPtr privconn = conn->privateData;
3286
    int numActive;
3287

3288 3289
    numActive = virNetworkObjListNumOfNetworks(privconn->networks,
                                               true, NULL, conn);
3290
    return numActive;
3291 3292
}

3293 3294 3295 3296 3297 3298

static int
testConnectListNetworks(virConnectPtr conn,
                        char **const names,
                        int nnames)
{
3299
    testDriverPtr privconn = conn->privateData;
3300
    int n;
3301

3302 3303
    n = virNetworkObjListGetNames(privconn->networks,
                                  true, names, nnames, NULL, conn);
3304
    return n;
3305 3306
}

3307 3308 3309

static int
testConnectNumOfDefinedNetworks(virConnectPtr conn)
3310
{
3311
    testDriverPtr privconn = conn->privateData;
3312
    int numInactive;
3313

3314 3315
    numInactive = virNetworkObjListNumOfNetworks(privconn->networks,
                                                 false, NULL, conn);
3316
    return numInactive;
3317 3318
}

3319 3320 3321 3322 3323 3324

static int
testConnectListDefinedNetworks(virConnectPtr conn,
                               char **const names,
                               int nnames)
{
3325
    testDriverPtr privconn = conn->privateData;
3326
    int n;
3327

3328 3329
    n = virNetworkObjListGetNames(privconn->networks,
                                  false, names, nnames, NULL, conn);
3330
    return n;
3331 3332
}

3333

3334
static int
3335
testConnectListAllNetworks(virConnectPtr conn,
3336 3337 3338
                           virNetworkPtr **nets,
                           unsigned int flags)
{
3339
    testDriverPtr privconn = conn->privateData;
3340 3341 3342

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

3343
    return virNetworkObjListExport(conn, privconn->networks, nets, NULL, flags);
3344
}
3345

3346 3347 3348

static int
testNetworkIsActive(virNetworkPtr net)
3349
{
3350
    testDriverPtr privconn = net->conn->privateData;
3351 3352 3353
    virNetworkObjPtr obj;
    int ret = -1;

3354
    if (!(obj = testNetworkObjFindByUUID(privconn, net->uuid)))
3355
        goto cleanup;
3356

3357 3358
    ret = virNetworkObjIsActive(obj);

3359
 cleanup:
3360
    virNetworkObjEndAPI(&obj);
3361 3362 3363
    return ret;
}

3364 3365 3366

static int
testNetworkIsPersistent(virNetworkPtr net)
3367
{
3368
    testDriverPtr privconn = net->conn->privateData;
3369 3370 3371
    virNetworkObjPtr obj;
    int ret = -1;

3372
    if (!(obj = testNetworkObjFindByUUID(privconn, net->uuid)))
3373
        goto cleanup;
3374

3375 3376
    ret = obj->persistent;

3377
 cleanup:
3378
    virNetworkObjEndAPI(&obj);
3379 3380 3381 3382
    return ret;
}


3383 3384
static virNetworkPtr
testNetworkCreateXML(virConnectPtr conn, const char *xml)
3385
{
3386
    testDriverPtr privconn = conn->privateData;
3387
    virNetworkDefPtr def;
3388
    virNetworkObjPtr net = NULL;
3389
    virNetworkPtr ret = NULL;
3390
    virObjectEventPtr event = NULL;
3391

3392
    if ((def = virNetworkDefParseString(xml)) == NULL)
3393
        goto cleanup;
3394

3395 3396 3397
    if (!(net = virNetworkObjAssignDef(privconn->networks, def,
                                       VIR_NETWORK_OBJ_LIST_ADD_LIVE |
                                       VIR_NETWORK_OBJ_LIST_ADD_CHECK_LIVE)))
3398 3399
        goto cleanup;
    def = NULL;
3400
    net->active = 1;
3401

3402
    event = virNetworkEventLifecycleNew(net->def->name, net->def->uuid,
3403 3404
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3405

3406
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3407

3408
 cleanup:
3409
    virNetworkDefFree(def);
3410
    testObjectEventQueue(privconn, event);
3411
    virNetworkObjEndAPI(&net);
3412
    return ret;
3413 3414
}

3415 3416 3417 3418

static virNetworkPtr
testNetworkDefineXML(virConnectPtr conn,
                     const char *xml)
3419
{
3420
    testDriverPtr privconn = conn->privateData;
3421
    virNetworkDefPtr def;
3422
    virNetworkObjPtr net = NULL;
3423
    virNetworkPtr ret = NULL;
3424
    virObjectEventPtr event = NULL;
3425

3426
    if ((def = virNetworkDefParseString(xml)) == NULL)
3427
        goto cleanup;
3428

3429
    if (!(net = virNetworkObjAssignDef(privconn->networks, def, 0)))
3430 3431
        goto cleanup;
    def = NULL;
3432

3433
    event = virNetworkEventLifecycleNew(net->def->name, net->def->uuid,
3434 3435
                                        VIR_NETWORK_EVENT_DEFINED,
                                        0);
3436

3437
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3438

3439
 cleanup:
3440
    virNetworkDefFree(def);
3441
    testObjectEventQueue(privconn, event);
3442
    virNetworkObjEndAPI(&net);
3443
    return ret;
3444 3445
}

3446 3447 3448

static int
testNetworkUndefine(virNetworkPtr network)
3449
{
3450
    testDriverPtr privconn = network->conn->privateData;
3451
    virNetworkObjPtr privnet;
3452
    int ret = -1;
3453
    virObjectEventPtr event = NULL;
3454

3455
    if (!(privnet = testNetworkObjFindByName(privconn, network->name)))
3456
        goto cleanup;
3457

D
Daniel P. Berrange 已提交
3458
    if (virNetworkObjIsActive(privnet)) {
3459 3460
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is still running"), network->name);
3461
        goto cleanup;
3462 3463
    }

3464
    event = virNetworkEventLifecycleNew(network->name, network->uuid,
3465 3466
                                        VIR_NETWORK_EVENT_UNDEFINED,
                                        0);
3467

3468
    virNetworkObjRemoveInactive(privconn->networks, privnet);
3469
    ret = 0;
3470

3471
 cleanup:
3472
    testObjectEventQueue(privconn, event);
3473
    virNetworkObjEndAPI(&privnet);
3474
    return ret;
3475 3476
}

3477

3478 3479 3480 3481 3482 3483 3484 3485
static int
testNetworkUpdate(virNetworkPtr net,
                  unsigned int command,
                  unsigned int section,
                  int parentIndex,
                  const char *xml,
                  unsigned int flags)
{
3486
    testDriverPtr privconn = net->conn->privateData;
3487 3488 3489 3490 3491 3492 3493
    virNetworkObjPtr network = NULL;
    int isActive, ret = -1;

    virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
                  VIR_NETWORK_UPDATE_AFFECT_CONFIG,
                  -1);

3494
    if (!(network = testNetworkObjFindByUUID(privconn, net->uuid)))
3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514
        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;
3515
 cleanup:
3516
    virNetworkObjEndAPI(&network);
3517 3518 3519
    return ret;
}

3520 3521 3522

static int
testNetworkCreate(virNetworkPtr network)
3523
{
3524
    testDriverPtr privconn = network->conn->privateData;
3525
    virNetworkObjPtr privnet;
3526
    int ret = -1;
3527
    virObjectEventPtr event = NULL;
3528

3529
    if (!(privnet = testNetworkObjFindByName(privconn, network->name)))
3530
        goto cleanup;
3531

D
Daniel P. Berrange 已提交
3532
    if (virNetworkObjIsActive(privnet)) {
3533 3534
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is already running"), network->name);
3535
        goto cleanup;
3536 3537
    }

3538
    privnet->active = 1;
3539
    event = virNetworkEventLifecycleNew(privnet->def->name, privnet->def->uuid,
3540 3541
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3542
    ret = 0;
3543

3544
 cleanup:
3545
    testObjectEventQueue(privconn, event);
3546
    virNetworkObjEndAPI(&privnet);
3547
    return ret;
3548 3549
}

3550 3551 3552

static int
testNetworkDestroy(virNetworkPtr network)
3553
{
3554
    testDriverPtr privconn = network->conn->privateData;
3555
    virNetworkObjPtr privnet;
3556
    int ret = -1;
3557
    virObjectEventPtr event = NULL;
3558

3559
    if (!(privnet = testNetworkObjFindByName(privconn, network->name)))
3560
        goto cleanup;
3561

3562
    privnet->active = 0;
3563
    event = virNetworkEventLifecycleNew(privnet->def->name, privnet->def->uuid,
3564 3565
                                        VIR_NETWORK_EVENT_STOPPED,
                                        0);
3566
    if (!privnet->persistent)
3567
        virNetworkObjRemoveInactive(privconn->networks, privnet);
3568

3569 3570
    ret = 0;

3571
 cleanup:
3572
    testObjectEventQueue(privconn, event);
3573
    virNetworkObjEndAPI(&privnet);
3574
    return ret;
3575 3576
}

3577 3578 3579 3580

static char *
testNetworkGetXMLDesc(virNetworkPtr network,
                      unsigned int flags)
3581
{
3582
    testDriverPtr privconn = network->conn->privateData;
3583
    virNetworkObjPtr privnet;
3584
    char *ret = NULL;
3585

E
Eric Blake 已提交
3586 3587
    virCheckFlags(0, NULL);

3588
    if (!(privnet = testNetworkObjFindByName(privconn, network->name)))
3589
        goto cleanup;
3590

3591
    ret = virNetworkDefFormat(privnet->def, flags);
3592

3593
 cleanup:
3594
    virNetworkObjEndAPI(&privnet);
3595
    return ret;
3596 3597
}

3598 3599 3600 3601

static char *
testNetworkGetBridgeName(virNetworkPtr network)
{
3602
    testDriverPtr privconn = network->conn->privateData;
3603
    char *bridge = NULL;
3604 3605
    virNetworkObjPtr privnet;

3606
    if (!(privnet = testNetworkObjFindByName(privconn, network->name)))
3607
        goto cleanup;
3608

3609
    if (!(privnet->def->bridge)) {
3610 3611 3612
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("network '%s' does not have a bridge name."),
                       privnet->def->name);
3613 3614 3615
        goto cleanup;
    }

3616
    ignore_value(VIR_STRDUP(bridge, privnet->def->bridge));
3617

3618
 cleanup:
3619
    virNetworkObjEndAPI(&privnet);
3620 3621 3622
    return bridge;
}

3623 3624 3625 3626

static int
testNetworkGetAutostart(virNetworkPtr network,
                        int *autostart)
3627
{
3628
    testDriverPtr privconn = network->conn->privateData;
3629
    virNetworkObjPtr privnet;
3630
    int ret = -1;
3631

3632
    if (!(privnet = testNetworkObjFindByName(privconn, network->name)))
3633
        goto cleanup;
3634

3635
    *autostart = privnet->autostart;
3636 3637
    ret = 0;

3638
 cleanup:
3639
    virNetworkObjEndAPI(&privnet);
3640
    return ret;
3641 3642
}

3643 3644 3645 3646

static int
testNetworkSetAutostart(virNetworkPtr network,
                        int autostart)
3647
{
3648
    testDriverPtr privconn = network->conn->privateData;
3649
    virNetworkObjPtr privnet;
3650
    int ret = -1;
3651

3652
    if (!(privnet = testNetworkObjFindByName(privconn, network->name)))
3653
        goto cleanup;
3654

3655
    privnet->autostart = autostart ? 1 : 0;
3656 3657
    ret = 0;

3658
 cleanup:
3659
    virNetworkObjEndAPI(&privnet);
3660
    return ret;
3661
}
3662

C
Cole Robinson 已提交
3663

L
Laine Stump 已提交
3664 3665 3666 3667 3668
/*
 * Physical host interface routines
 */


3669 3670 3671 3672
static virInterfaceObjPtr
testInterfaceObjFindByName(testDriverPtr privconn,
                           const char *name)
{
3673
    virInterfaceObjPtr obj;
3674 3675

    testDriverLock(privconn);
3676
    obj = virInterfaceObjListFindByName(privconn->ifaces, name);
3677 3678
    testDriverUnlock(privconn);

3679
    if (!obj)
3680 3681 3682 3683
        virReportError(VIR_ERR_NO_INTERFACE,
                       _("no interface with matching name '%s'"),
                       name);

3684
    return obj;
3685 3686 3687
}


3688 3689
static int
testConnectNumOfInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3690
{
3691
    testDriverPtr privconn = conn->privateData;
3692
    int ninterfaces;
L
Laine Stump 已提交
3693 3694

    testDriverLock(privconn);
3695
    ninterfaces = virInterfaceObjListNumOfInterfaces(privconn->ifaces, true);
L
Laine Stump 已提交
3696
    testDriverUnlock(privconn);
3697
    return ninterfaces;
L
Laine Stump 已提交
3698 3699
}

3700 3701 3702 3703 3704

static int
testConnectListInterfaces(virConnectPtr conn,
                          char **const names,
                          int maxnames)
L
Laine Stump 已提交
3705
{
3706
    testDriverPtr privconn = conn->privateData;
3707
    int nnames;
L
Laine Stump 已提交
3708 3709

    testDriverLock(privconn);
3710 3711
    nnames = virInterfaceObjListGetNames(privconn->ifaces, true,
                                         names, maxnames);
L
Laine Stump 已提交
3712 3713
    testDriverUnlock(privconn);

3714
    return nnames;
L
Laine Stump 已提交
3715 3716
}

3717 3718 3719

static int
testConnectNumOfDefinedInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3720
{
3721
    testDriverPtr privconn = conn->privateData;
3722
    int ninterfaces;
L
Laine Stump 已提交
3723 3724

    testDriverLock(privconn);
3725
    ninterfaces = virInterfaceObjListNumOfInterfaces(privconn->ifaces, false);
L
Laine Stump 已提交
3726
    testDriverUnlock(privconn);
3727
    return ninterfaces;
L
Laine Stump 已提交
3728 3729
}

3730 3731 3732 3733 3734

static int
testConnectListDefinedInterfaces(virConnectPtr conn,
                                 char **const names,
                                 int maxnames)
L
Laine Stump 已提交
3735
{
3736
    testDriverPtr privconn = conn->privateData;
3737
    int nnames;
L
Laine Stump 已提交
3738 3739

    testDriverLock(privconn);
3740 3741
    nnames = virInterfaceObjListGetNames(privconn->ifaces, false,
                                         names, maxnames);
L
Laine Stump 已提交
3742 3743
    testDriverUnlock(privconn);

3744
    return nnames;
L
Laine Stump 已提交
3745 3746
}

3747 3748 3749 3750

static virInterfacePtr
testInterfaceLookupByName(virConnectPtr conn,
                          const char *name)
L
Laine Stump 已提交
3751
{
3752
    testDriverPtr privconn = conn->privateData;
3753
    virInterfaceObjPtr obj;
3754
    virInterfaceDefPtr def;
L
Laine Stump 已提交
3755 3756
    virInterfacePtr ret = NULL;

3757
    if (!(obj = testInterfaceObjFindByName(privconn, name)))
3758
        return NULL;
3759
    def = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
3760

3761
    ret = virGetInterface(conn, def->name, def->mac);
L
Laine Stump 已提交
3762

3763
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
3764 3765 3766
    return ret;
}

3767 3768 3769 3770

static virInterfacePtr
testInterfaceLookupByMACString(virConnectPtr conn,
                               const char *mac)
L
Laine Stump 已提交
3771
{
3772
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3773
    int ifacect;
3774
    char *ifacenames[] = { NULL, NULL };
L
Laine Stump 已提交
3775 3776 3777
    virInterfacePtr ret = NULL;

    testDriverLock(privconn);
3778 3779
    ifacect = virInterfaceObjListFindByMACString(privconn->ifaces, mac,
                                                 ifacenames, 2);
L
Laine Stump 已提交
3780 3781 3782
    testDriverUnlock(privconn);

    if (ifacect == 0) {
3783 3784
        virReportError(VIR_ERR_NO_INTERFACE,
                       _("no interface with matching mac '%s'"), mac);
L
Laine Stump 已提交
3785 3786 3787 3788
        goto cleanup;
    }

    if (ifacect > 1) {
3789
        virReportError(VIR_ERR_MULTIPLE_INTERFACES, NULL);
L
Laine Stump 已提交
3790 3791 3792
        goto cleanup;
    }

3793
    ret = virGetInterface(conn, ifacenames[0], mac);
L
Laine Stump 已提交
3794

3795
 cleanup:
3796 3797
    VIR_FREE(ifacenames[0]);
    VIR_FREE(ifacenames[1]);
L
Laine Stump 已提交
3798 3799 3800
    return ret;
}

3801 3802 3803

static int
testInterfaceIsActive(virInterfacePtr iface)
3804
{
3805
    testDriverPtr privconn = iface->conn->privateData;
3806 3807 3808
    virInterfaceObjPtr obj;
    int ret = -1;

3809
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
3810
        return -1;
3811

3812 3813
    ret = virInterfaceObjIsActive(obj);

3814
    virInterfaceObjEndAPI(&obj);
3815 3816 3817
    return ret;
}

3818 3819 3820 3821

static int
testInterfaceChangeBegin(virConnectPtr conn,
                         unsigned int flags)
3822
{
3823
    testDriverPtr privconn = conn->privateData;
3824 3825
    int ret = -1;

E
Eric Blake 已提交
3826 3827
    virCheckFlags(0, -1);

3828 3829
    testDriverLock(privconn);
    if (privconn->transaction_running) {
3830
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3831
                       _("there is another transaction running."));
3832 3833 3834 3835 3836
        goto cleanup;
    }

    privconn->transaction_running = true;

3837
    if (!(privconn->backupIfaces = virInterfaceObjListClone(privconn->ifaces)))
3838 3839 3840
        goto cleanup;

    ret = 0;
3841
 cleanup:
3842 3843 3844 3845
    testDriverUnlock(privconn);
    return ret;
}

3846 3847 3848 3849

static int
testInterfaceChangeCommit(virConnectPtr conn,
                          unsigned int flags)
3850
{
3851
    testDriverPtr privconn = conn->privateData;
3852 3853
    int ret = -1;

E
Eric Blake 已提交
3854 3855
    virCheckFlags(0, -1);

3856 3857 3858
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3859
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3860 3861
                       _("no transaction running, "
                         "nothing to be committed."));
3862 3863 3864
        goto cleanup;
    }

3865
    virInterfaceObjListFree(privconn->backupIfaces);
3866 3867 3868 3869
    privconn->transaction_running = false;

    ret = 0;

3870
 cleanup:
3871 3872 3873 3874 3875
    testDriverUnlock(privconn);

    return ret;
}

3876 3877 3878 3879

static int
testInterfaceChangeRollback(virConnectPtr conn,
                            unsigned int flags)
3880
{
3881
    testDriverPtr privconn = conn->privateData;
3882 3883
    int ret = -1;

E
Eric Blake 已提交
3884 3885
    virCheckFlags(0, -1);

3886 3887 3888
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3889
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3890 3891
                       _("no transaction running, "
                         "nothing to rollback."));
3892 3893 3894
        goto cleanup;
    }

3895 3896 3897
    virInterfaceObjListFree(privconn->ifaces);
    privconn->ifaces = privconn->backupIfaces;
    privconn->backupIfaces = NULL;
3898 3899 3900 3901 3902

    privconn->transaction_running = false;

    ret = 0;

3903
 cleanup:
3904 3905 3906
    testDriverUnlock(privconn);
    return ret;
}
3907

3908 3909 3910 3911

static char *
testInterfaceGetXMLDesc(virInterfacePtr iface,
                        unsigned int flags)
L
Laine Stump 已提交
3912
{
3913
    testDriverPtr privconn = iface->conn->privateData;
3914
    virInterfaceObjPtr obj;
3915
    virInterfaceDefPtr def;
L
Laine Stump 已提交
3916 3917
    char *ret = NULL;

E
Eric Blake 已提交
3918 3919
    virCheckFlags(0, NULL);

3920
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
3921
        return NULL;
3922
    def = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
3923

3924
    ret = virInterfaceDefFormat(def);
L
Laine Stump 已提交
3925

3926
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
3927 3928 3929 3930
    return ret;
}


3931 3932 3933 3934
static virInterfacePtr
testInterfaceDefineXML(virConnectPtr conn,
                       const char *xmlStr,
                       unsigned int flags)
L
Laine Stump 已提交
3935
{
3936
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3937
    virInterfaceDefPtr def;
3938
    virInterfaceObjPtr obj = NULL;
3939
    virInterfaceDefPtr objdef;
L
Laine Stump 已提交
3940 3941
    virInterfacePtr ret = NULL;

E
Eric Blake 已提交
3942 3943
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
3944
    testDriverLock(privconn);
3945
    if ((def = virInterfaceDefParseString(xmlStr)) == NULL)
L
Laine Stump 已提交
3946 3947
        goto cleanup;

3948
    if ((obj = virInterfaceObjListAssignDef(privconn->ifaces, def)) == NULL)
L
Laine Stump 已提交
3949 3950
        goto cleanup;
    def = NULL;
3951
    objdef = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
3952

3953
    ret = virGetInterface(conn, objdef->name, objdef->mac);
L
Laine Stump 已提交
3954

3955
 cleanup:
L
Laine Stump 已提交
3956
    virInterfaceDefFree(def);
3957
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
3958 3959 3960 3961
    testDriverUnlock(privconn);
    return ret;
}

3962 3963 3964

static int
testInterfaceUndefine(virInterfacePtr iface)
L
Laine Stump 已提交
3965
{
3966
    testDriverPtr privconn = iface->conn->privateData;
3967
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
3968

3969
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
3970
        return -1;
L
Laine Stump 已提交
3971

3972
    virInterfaceObjListRemove(privconn->ifaces, obj);
3973
    virObjectUnref(obj);
L
Laine Stump 已提交
3974

3975
    return 0;
L
Laine Stump 已提交
3976 3977
}

3978 3979 3980 3981

static int
testInterfaceCreate(virInterfacePtr iface,
                    unsigned int flags)
L
Laine Stump 已提交
3982
{
3983
    testDriverPtr privconn = iface->conn->privateData;
3984
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
3985 3986
    int ret = -1;

E
Eric Blake 已提交
3987 3988
    virCheckFlags(0, -1);

3989
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
3990
        return -1;
L
Laine Stump 已提交
3991

3992
    if (virInterfaceObjIsActive(obj)) {
3993
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
3994 3995 3996
        goto cleanup;
    }

3997
    virInterfaceObjSetActive(obj, true);
L
Laine Stump 已提交
3998 3999
    ret = 0;

4000
 cleanup:
4001
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
4002 4003 4004
    return ret;
}

4005 4006 4007 4008

static int
testInterfaceDestroy(virInterfacePtr iface,
                     unsigned int flags)
L
Laine Stump 已提交
4009
{
4010
    testDriverPtr privconn = iface->conn->privateData;
4011
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
4012 4013
    int ret = -1;

E
Eric Blake 已提交
4014 4015
    virCheckFlags(0, -1);

4016
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
4017
        return -1;
L
Laine Stump 已提交
4018

4019
    if (!virInterfaceObjIsActive(obj)) {
4020
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
4021 4022 4023
        goto cleanup;
    }

4024
    virInterfaceObjSetActive(obj, false);
L
Laine Stump 已提交
4025 4026
    ret = 0;

4027
 cleanup:
4028
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
4029 4030 4031 4032 4033
    return ret;
}



C
Cole Robinson 已提交
4034 4035 4036 4037
/*
 * Storage Driver routines
 */

4038

4039 4040
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool)
{
C
Cole Robinson 已提交
4041 4042 4043 4044 4045

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

4046
    return VIR_STRDUP(pool->configFile, "");
C
Cole Robinson 已提交
4047 4048
}

4049

4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068
static virStoragePoolObjPtr
testStoragePoolObjFindByName(testDriverPtr privconn,
                             const char *name)
{
    virStoragePoolObjPtr pool;

    testDriverLock(privconn);
    pool = virStoragePoolObjFindByName(&privconn->pools, name);
    testDriverUnlock(privconn);

    if (!pool)
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       name);

    return pool;
}


4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090
static virStoragePoolObjPtr
testStoragePoolObjFindByUUID(testDriverPtr privconn,
                             const unsigned char *uuid)
{
    virStoragePoolObjPtr pool;
    char uuidstr[VIR_UUID_STRING_BUFLEN];

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

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

    return pool;
}


C
Cole Robinson 已提交
4091 4092
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
4093 4094
                            const unsigned char *uuid)
{
4095
    testDriverPtr privconn = conn->privateData;
4096 4097
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4098

4099
    if (!(pool = testStoragePoolObjFindByUUID(privconn, uuid)))
4100
        goto cleanup;
C
Cole Robinson 已提交
4101

4102 4103
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4104

4105
 cleanup:
4106 4107
    if (pool)
        virStoragePoolObjUnlock(pool);
4108
    return ret;
C
Cole Robinson 已提交
4109 4110 4111 4112
}

static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
4113 4114
                            const char *name)
{
4115
    testDriverPtr privconn = conn->privateData;
4116 4117
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4118

4119
    if (!(pool = testStoragePoolObjFindByName(privconn, name)))
4120
        goto cleanup;
C
Cole Robinson 已提交
4121

4122 4123
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4124

4125
 cleanup:
4126 4127
    if (pool)
        virStoragePoolObjUnlock(pool);
4128
    return ret;
C
Cole Robinson 已提交
4129 4130 4131
}

static virStoragePoolPtr
4132 4133
testStoragePoolLookupByVolume(virStorageVolPtr vol)
{
C
Cole Robinson 已提交
4134 4135 4136
    return testStoragePoolLookupByName(vol->conn, vol->pool);
}

4137

C
Cole Robinson 已提交
4138
static int
4139 4140
testConnectNumOfStoragePools(virConnectPtr conn)
{
4141
    testDriverPtr privconn = conn->privateData;
4142
    int numActive = 0;
C
Cole Robinson 已提交
4143

4144
    testDriverLock(privconn);
4145 4146
    numActive = virStoragePoolObjNumOfStoragePools(&privconn->pools, conn,
                                                   true, NULL);
4147
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4148 4149 4150 4151

    return numActive;
}

4152

C
Cole Robinson 已提交
4153
static int
4154 4155
testConnectListStoragePools(virConnectPtr conn,
                            char **const names,
4156
                            int maxnames)
4157
{
4158
    testDriverPtr privconn = conn->privateData;
4159
    int n = 0;
C
Cole Robinson 已提交
4160

4161
    testDriverLock(privconn);
4162 4163
    n = virStoragePoolObjGetNames(&privconn->pools, conn, true, NULL,
                                  names, maxnames);
4164
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4165 4166 4167 4168

    return n;
}

4169

C
Cole Robinson 已提交
4170
static int
4171 4172
testConnectNumOfDefinedStoragePools(virConnectPtr conn)
{
4173
    testDriverPtr privconn = conn->privateData;
4174
    int numInactive = 0;
C
Cole Robinson 已提交
4175

4176
    testDriverLock(privconn);
4177 4178
    numInactive = virStoragePoolObjNumOfStoragePools(&privconn->pools, conn,
                                                     false, NULL);
4179
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4180 4181 4182 4183

    return numInactive;
}

4184

C
Cole Robinson 已提交
4185
static int
4186 4187
testConnectListDefinedStoragePools(virConnectPtr conn,
                                   char **const names,
4188
                                   int maxnames)
4189
{
4190
    testDriverPtr privconn = conn->privateData;
4191
    int n = 0;
C
Cole Robinson 已提交
4192

4193
    testDriverLock(privconn);
4194 4195
    n = virStoragePoolObjGetNames(&privconn->pools, conn, false, NULL,
                                  names, maxnames);
4196
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4197 4198 4199 4200

    return n;
}

4201
static int
4202 4203 4204
testConnectListAllStoragePools(virConnectPtr conn,
                               virStoragePoolPtr **pools,
                               unsigned int flags)
4205
{
4206
    testDriverPtr privconn = conn->privateData;
4207 4208 4209 4210 4211
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

    testDriverLock(privconn);
J
John Ferlan 已提交
4212
    ret = virStoragePoolObjListExport(conn, &privconn->pools, pools,
4213
                                      NULL, flags);
4214 4215 4216 4217
    testDriverUnlock(privconn);

    return ret;
}
C
Cole Robinson 已提交
4218

4219 4220
static int testStoragePoolIsActive(virStoragePoolPtr pool)
{
4221
    testDriverPtr privconn = pool->conn->privateData;
4222 4223 4224
    virStoragePoolObjPtr obj;
    int ret = -1;

4225
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
4226
        goto cleanup;
4227

4228 4229
    ret = virStoragePoolObjIsActive(obj);

4230
 cleanup:
4231 4232 4233 4234 4235 4236 4237
    if (obj)
        virStoragePoolObjUnlock(obj);
    return ret;
}

static int testStoragePoolIsPersistent(virStoragePoolPtr pool)
{
4238
    testDriverPtr privconn = pool->conn->privateData;
4239 4240 4241
    virStoragePoolObjPtr obj;
    int ret = -1;

4242
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
4243
        goto cleanup;
4244

4245 4246
    ret = obj->configFile ? 1 : 0;

4247
 cleanup:
4248 4249 4250 4251 4252 4253 4254
    if (obj)
        virStoragePoolObjUnlock(obj);
    return ret;
}



C
Cole Robinson 已提交
4255
static int
4256 4257
testStoragePoolCreate(virStoragePoolPtr pool,
                      unsigned int flags)
E
Eric Blake 已提交
4258
{
4259
    testDriverPtr privconn = pool->conn->privateData;
4260
    virStoragePoolObjPtr privpool;
4261
    int ret = -1;
4262
    virObjectEventPtr event = NULL;
4263

E
Eric Blake 已提交
4264 4265
    virCheckFlags(0, -1);

4266
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4267
        goto cleanup;
4268

4269
    if (virStoragePoolObjIsActive(privpool)) {
4270 4271
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4272 4273
        goto cleanup;
    }
C
Cole Robinson 已提交
4274 4275

    privpool->active = 1;
4276 4277 4278 4279

    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_STARTED,
                                            0);
4280
    ret = 0;
C
Cole Robinson 已提交
4281

4282
 cleanup:
4283
    testObjectEventQueue(privconn, event);
4284 4285
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4286
    return ret;
C
Cole Robinson 已提交
4287 4288 4289
}

static char *
4290 4291 4292 4293
testConnectFindStoragePoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type,
                                  const char *srcSpec,
                                  unsigned int flags)
C
Cole Robinson 已提交
4294
{
4295 4296 4297 4298
    virStoragePoolSourcePtr source = NULL;
    int pool_type;
    char *ret = NULL;

E
Eric Blake 已提交
4299 4300
    virCheckFlags(0, NULL);

4301 4302
    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
4303 4304
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
4305 4306 4307 4308
        goto cleanup;
    }

    if (srcSpec) {
4309
        source = virStoragePoolDefParseSourceString(srcSpec, pool_type);
4310 4311 4312 4313 4314 4315 4316
        if (!source)
            goto cleanup;
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
4317
        ignore_value(VIR_STRDUP(ret, defaultPoolSourcesLogicalXML));
4318 4319 4320
        break;

    case VIR_STORAGE_POOL_NETFS:
4321
        if (!source || !source->hosts[0].name) {
4322 4323
            virReportError(VIR_ERR_INVALID_ARG,
                           "%s", _("hostname must be specified for netfs sources"));
4324 4325 4326
            goto cleanup;
        }

4327 4328
        ignore_value(virAsprintf(&ret, defaultPoolSourcesNetFSXML,
                                 source->hosts[0].name));
4329 4330 4331
        break;

    default:
4332 4333
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source discovery"), type);
4334 4335
    }

4336
 cleanup:
4337 4338
    virStoragePoolSourceFree(source);
    return ret;
C
Cole Robinson 已提交
4339 4340 4341
}


4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369
static virNodeDeviceObjPtr
testNodeDeviceMockCreateVport(testDriverPtr driver,
                              const char *wwnn,
                              const char *wwpn);
static int
testCreateVport(testDriverPtr driver,
                const char *wwnn,
                const char *wwpn)
{
    virNodeDeviceObjPtr obj = NULL;
    /* The storage_backend_scsi createVport() will use the input adapter
     * fields parent name, parent_wwnn/parent_wwpn, or parent_fabric_wwn
     * in order to determine whether the provided parent can be used to
     * create a vHBA or will find "an available vport capable" to create
     * a vHBA. In order to do this, it uses the virVHBA* API's which traverse
     * the sysfs looking at various fields (rather than going via nodedev).
     *
     * Since the test environ doesn't have the sysfs for the storage pool
     * test, at least for now use the node device test infrastructure to
     * create the vHBA. In the long run the result is the same. */
    if (!(obj = testNodeDeviceMockCreateVport(driver, wwnn, wwpn)))
        return -1;
    virNodeDeviceObjUnlock(obj);

    return 0;
}


C
Cole Robinson 已提交
4370
static virStoragePoolPtr
4371 4372 4373
testStoragePoolCreateXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4374
{
4375
    testDriverPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4376
    virStoragePoolDefPtr def;
4377
    virStoragePoolObjPtr pool = NULL;
4378
    virStoragePoolPtr ret = NULL;
4379
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
4380

E
Eric Blake 已提交
4381 4382
    virCheckFlags(0, NULL);

4383
    testDriverLock(privconn);
4384
    if (!(def = virStoragePoolDefParseString(xml)))
4385
        goto cleanup;
C
Cole Robinson 已提交
4386

4387 4388 4389 4390
    pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid);
    if (!pool)
        pool = virStoragePoolObjFindByName(&privconn->pools, def->name);
    if (pool) {
4391 4392
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("storage pool already exists"));
4393
        goto cleanup;
C
Cole Robinson 已提交
4394 4395
    }

4396
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4397
        goto cleanup;
4398
    def = NULL;
C
Cole Robinson 已提交
4399

4400
    if (pool->def->source.adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413
        /* In the real code, we'd call virVHBAManageVport followed by
         * find_new_device, but we cannot do that here since we're not
         * mocking udev. The mock routine will copy an existing vHBA and
         * rename a few fields to mock that. */
        if (testCreateVport(privconn,
                            pool->def->source.adapter.data.fchost.wwnn,
                            pool->def->source.adapter.data.fchost.wwpn) < 0) {
            virStoragePoolObjRemove(&privconn->pools, pool);
            pool = NULL;
            goto cleanup;
        }
    }

4414
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4415
        virStoragePoolObjRemove(&privconn->pools, pool);
4416 4417
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4418
    }
4419 4420 4421 4422 4423 4424

    /* *SetDefaults fills this in for the persistent pools, but this
     * would be a transient pool so remove it; otherwise, the Destroy
     * code will not Remove the pool */
    VIR_FREE(pool->configFile);

C
Cole Robinson 已提交
4425 4426
    pool->active = 1;

4427 4428 4429 4430
    event = virStoragePoolEventLifecycleNew(pool->def->name, pool->def->uuid,
                                            VIR_STORAGE_POOL_EVENT_STARTED,
                                            0);

4431 4432
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4433

4434
 cleanup:
4435
    virStoragePoolDefFree(def);
4436
    testObjectEventQueue(privconn, event);
4437 4438 4439
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4440
    return ret;
C
Cole Robinson 已提交
4441 4442 4443
}

static virStoragePoolPtr
4444 4445 4446
testStoragePoolDefineXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4447
{
4448
    testDriverPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4449
    virStoragePoolDefPtr def;
4450
    virStoragePoolObjPtr pool = NULL;
4451
    virStoragePoolPtr ret = NULL;
4452
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
4453

E
Eric Blake 已提交
4454 4455
    virCheckFlags(0, NULL);

4456
    testDriverLock(privconn);
4457
    if (!(def = virStoragePoolDefParseString(xml)))
4458
        goto cleanup;
C
Cole Robinson 已提交
4459 4460 4461 4462 4463

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

4464
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4465 4466
        goto cleanup;
    def = NULL;
C
Cole Robinson 已提交
4467

4468 4469 4470 4471
    event = virStoragePoolEventLifecycleNew(pool->def->name, pool->def->uuid,
                                            VIR_STORAGE_POOL_EVENT_DEFINED,
                                            0);

4472
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4473
        virStoragePoolObjRemove(&privconn->pools, pool);
4474 4475
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4476 4477
    }

4478 4479
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4480

4481
 cleanup:
4482
    virStoragePoolDefFree(def);
4483
    testObjectEventQueue(privconn, event);
4484 4485 4486
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4487
    return ret;
C
Cole Robinson 已提交
4488 4489 4490
}

static int
4491 4492
testStoragePoolUndefine(virStoragePoolPtr pool)
{
4493
    testDriverPtr privconn = pool->conn->privateData;
4494
    virStoragePoolObjPtr privpool;
4495
    int ret = -1;
4496
    virObjectEventPtr event = NULL;
4497

4498
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4499
        goto cleanup;
4500

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

4507 4508 4509 4510
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_UNDEFINED,
                                            0);

C
Cole Robinson 已提交
4511
    virStoragePoolObjRemove(&privconn->pools, privpool);
4512
    privpool = NULL;
4513
    ret = 0;
C
Cole Robinson 已提交
4514

4515
 cleanup:
4516 4517
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4518
    testObjectEventQueue(privconn, event);
4519
    return ret;
C
Cole Robinson 已提交
4520 4521 4522
}

static int
4523
testStoragePoolBuild(virStoragePoolPtr pool,
E
Eric Blake 已提交
4524 4525
                     unsigned int flags)
{
4526
    testDriverPtr privconn = pool->conn->privateData;
4527
    virStoragePoolObjPtr privpool;
4528
    int ret = -1;
4529

E
Eric Blake 已提交
4530 4531
    virCheckFlags(0, -1);

4532
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4533
        goto cleanup;
4534

4535
    if (virStoragePoolObjIsActive(privpool)) {
4536 4537
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4538 4539
        goto cleanup;
    }
4540
    ret = 0;
C
Cole Robinson 已提交
4541

4542
 cleanup:
4543 4544
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4545
    return ret;
C
Cole Robinson 已提交
4546 4547 4548
}


4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563
static int
testDestroyVport(testDriverPtr privconn,
                 const char *wwnn ATTRIBUTE_UNUSED,
                 const char *wwpn ATTRIBUTE_UNUSED)
{
    virNodeDeviceObjPtr obj = NULL;
    virObjectEventPtr event = NULL;

    /* NB: Cannot use virVHBAGetHostByWWN (yet) like the storage_backend_scsi
     * deleteVport() helper since that traverses the file system looking for
     * the wwnn/wwpn. So our choice short term is to cheat and use the name
     * (scsi_host12) we know was created.
     *
     * Reaching across the boundaries of space and time into the
     * Node Device in order to remove */
4564
    if (!(obj = virNodeDeviceObjFindByName(privconn->devs, "scsi_host12"))) {
4565 4566
        virReportError(VIR_ERR_NO_NODE_DEVICE, "%s",
                       _("no node device with matching name 'scsi_host12'"));
4567
        return -1;
4568 4569 4570 4571 4572 4573
    }

    event = virNodeDeviceEventLifecycleNew("scsi_host12",
                                           VIR_NODE_DEVICE_EVENT_DELETED,
                                           0);

4574
    virNodeDeviceObjRemove(privconn->devs, obj);
4575
    virNodeDeviceObjFree(obj);
4576 4577

    testObjectEventQueue(privconn, event);
4578
    return 0;
4579 4580 4581
}


C
Cole Robinson 已提交
4582
static int
4583 4584
testStoragePoolDestroy(virStoragePoolPtr pool)
{
4585
    testDriverPtr privconn = pool->conn->privateData;
4586
    virStoragePoolObjPtr privpool;
4587
    int ret = -1;
4588
    virObjectEventPtr event = NULL;
4589

4590
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4591
        return -1;
4592 4593

    if (!virStoragePoolObjIsActive(privpool)) {
4594 4595
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4596
        goto cleanup;
4597
    }
C
Cole Robinson 已提交
4598 4599

    privpool->active = 0;
4600 4601

    if (privpool->def->source.adapter.type ==
4602
        VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
4603 4604 4605 4606 4607 4608 4609 4610
        if (testDestroyVport(privconn,
                             privpool->def->source.adapter.data.fchost.wwnn,
                             privpool->def->source.adapter.data.fchost.wwpn) < 0)
            goto cleanup;
    }

    event = virStoragePoolEventLifecycleNew(privpool->def->name,
                                            privpool->def->uuid,
4611 4612
                                            VIR_STORAGE_POOL_EVENT_STOPPED,
                                            0);
C
Cole Robinson 已提交
4613

4614
    if (privpool->configFile == NULL) {
C
Cole Robinson 已提交
4615
        virStoragePoolObjRemove(&privconn->pools, privpool);
4616 4617
        privpool = NULL;
    }
4618
    ret = 0;
C
Cole Robinson 已提交
4619

4620
 cleanup:
4621
    testObjectEventQueue(privconn, event);
4622 4623
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4624
    return ret;
C
Cole Robinson 已提交
4625 4626 4627 4628
}


static int
4629
testStoragePoolDelete(virStoragePoolPtr pool,
E
Eric Blake 已提交
4630 4631
                      unsigned int flags)
{
4632
    testDriverPtr privconn = pool->conn->privateData;
4633
    virStoragePoolObjPtr privpool;
4634
    int ret = -1;
4635

E
Eric Blake 已提交
4636 4637
    virCheckFlags(0, -1);

4638
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4639 4640 4641
        goto cleanup;

    if (virStoragePoolObjIsActive(privpool)) {
4642 4643
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4644
        goto cleanup;
4645 4646
    }

4647
    ret = 0;
C
Cole Robinson 已提交
4648

4649
 cleanup:
4650 4651
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4652
    return ret;
C
Cole Robinson 已提交
4653 4654 4655 4656
}


static int
4657
testStoragePoolRefresh(virStoragePoolPtr pool,
E
Eric Blake 已提交
4658 4659
                       unsigned int flags)
{
4660
    testDriverPtr privconn = pool->conn->privateData;
4661
    virStoragePoolObjPtr privpool;
4662
    int ret = -1;
4663
    virObjectEventPtr event = NULL;
4664

E
Eric Blake 已提交
4665 4666
    virCheckFlags(0, -1);

4667
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4668
        goto cleanup;
4669 4670

    if (!virStoragePoolObjIsActive(privpool)) {
4671 4672
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4673
        goto cleanup;
4674
    }
4675

4676
    event = virStoragePoolEventRefreshNew(pool->name, pool->uuid);
4677
    ret = 0;
C
Cole Robinson 已提交
4678

4679
 cleanup:
4680
    testObjectEventQueue(privconn, event);
4681 4682
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4683
    return ret;
C
Cole Robinson 已提交
4684 4685 4686 4687
}


static int
4688
testStoragePoolGetInfo(virStoragePoolPtr pool,
4689 4690
                       virStoragePoolInfoPtr info)
{
4691
    testDriverPtr privconn = pool->conn->privateData;
4692
    virStoragePoolObjPtr privpool;
4693
    int ret = -1;
4694

4695
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4696
        goto cleanup;
C
Cole Robinson 已提交
4697 4698 4699 4700 4701 4702 4703 4704 4705

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

4708
 cleanup:
4709 4710
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4711
    return ret;
C
Cole Robinson 已提交
4712 4713 4714
}

static char *
4715
testStoragePoolGetXMLDesc(virStoragePoolPtr pool,
E
Eric Blake 已提交
4716 4717
                          unsigned int flags)
{
4718
    testDriverPtr privconn = pool->conn->privateData;
4719
    virStoragePoolObjPtr privpool;
4720
    char *ret = NULL;
4721

E
Eric Blake 已提交
4722 4723
    virCheckFlags(0, NULL);

4724
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4725
        goto cleanup;
4726

4727
    ret = virStoragePoolDefFormat(privpool->def);
4728

4729
 cleanup:
4730 4731
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4732
    return ret;
C
Cole Robinson 已提交
4733 4734 4735
}

static int
4736
testStoragePoolGetAutostart(virStoragePoolPtr pool,
4737 4738
                            int *autostart)
{
4739
    testDriverPtr privconn = pool->conn->privateData;
4740
    virStoragePoolObjPtr privpool;
4741
    int ret = -1;
4742

4743
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4744
        goto cleanup;
C
Cole Robinson 已提交
4745 4746 4747 4748 4749 4750

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

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

static int
4760
testStoragePoolSetAutostart(virStoragePoolPtr pool,
4761 4762
                            int autostart)
{
4763
    testDriverPtr privconn = pool->conn->privateData;
4764
    virStoragePoolObjPtr privpool;
4765
    int ret = -1;
4766

4767
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4768
        goto cleanup;
C
Cole Robinson 已提交
4769 4770

    if (!privpool->configFile) {
4771 4772
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("pool has no config file"));
4773
        goto cleanup;
C
Cole Robinson 已提交
4774 4775 4776 4777
    }

    autostart = (autostart != 0);
    privpool->autostart = autostart;
4778 4779
    ret = 0;

4780
 cleanup:
4781 4782
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4783
    return ret;
C
Cole Robinson 已提交
4784 4785 4786 4787
}


static int
4788 4789
testStoragePoolNumOfVolumes(virStoragePoolPtr pool)
{
4790
    testDriverPtr privconn = pool->conn->privateData;
4791
    virStoragePoolObjPtr privpool;
4792
    int ret = -1;
4793

4794
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4795
        goto cleanup;
4796 4797

    if (!virStoragePoolObjIsActive(privpool)) {
4798 4799
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4800
        goto cleanup;
4801
    }
C
Cole Robinson 已提交
4802

4803 4804
    ret = virStoragePoolObjNumOfVolumes(&privpool->volumes, pool->conn,
                                        privpool->def, NULL);
4805

4806
 cleanup:
4807 4808
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4809
    return ret;
C
Cole Robinson 已提交
4810 4811
}

4812

C
Cole Robinson 已提交
4813
static int
4814
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4815
                           char **const names,
4816 4817
                           int maxnames)
{
4818
    testDriverPtr privconn = pool->conn->privateData;
4819
    virStoragePoolObjPtr privpool;
4820
    int n = -1;
4821

4822
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4823
        return -1;
4824 4825

    if (!virStoragePoolObjIsActive(privpool)) {
4826 4827
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4828
        goto cleanup;
4829 4830
    }

4831 4832
    n = virStoragePoolObjVolumeGetNames(&privpool->volumes, pool->conn,
                                        privpool->def, NULL, names, maxnames);
C
Cole Robinson 已提交
4833

4834
 cleanup:
4835
    virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4836 4837 4838
    return n;
}

4839

4840 4841 4842
static int
testStoragePoolListAllVolumes(virStoragePoolPtr obj,
                              virStorageVolPtr **vols,
4843 4844
                              unsigned int flags)
{
4845
    testDriverPtr privconn = obj->conn->privateData;
4846 4847 4848 4849 4850
    virStoragePoolObjPtr pool;
    int ret = -1;

    virCheckFlags(0, -1);

4851
    if (!(pool = testStoragePoolObjFindByUUID(privconn, obj->uuid)))
4852
        return -1;
4853 4854 4855 4856 4857 4858 4859

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

4860 4861
    ret = virStoragePoolObjVolumeListExport(obj->conn, &pool->volumes,
                                            pool->def, vols, NULL);
4862 4863

 cleanup:
4864
    virStoragePoolObjUnlock(pool);
4865 4866 4867

    return ret;
}
C
Cole Robinson 已提交
4868 4869

static virStorageVolPtr
4870
testStorageVolLookupByName(virStoragePoolPtr pool,
4871 4872
                           const char *name ATTRIBUTE_UNUSED)
{
4873
    testDriverPtr privconn = pool->conn->privateData;
4874 4875
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
4876
    virStorageVolPtr ret = NULL;
4877

4878
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4879
        goto cleanup;
4880 4881

    if (!virStoragePoolObjIsActive(privpool)) {
4882 4883
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4884
        goto cleanup;
4885 4886 4887 4888 4889
    }

    privvol = virStorageVolDefFindByName(privpool, name);

    if (!privvol) {
4890 4891
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"), name);
4892
        goto cleanup;
C
Cole Robinson 已提交
4893 4894
    }

4895
    ret = virGetStorageVol(pool->conn, privpool->def->name,
4896 4897
                           privvol->name, privvol->key,
                           NULL, NULL);
4898

4899
 cleanup:
4900 4901
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4902
    return ret;
C
Cole Robinson 已提交
4903 4904 4905 4906
}


static virStorageVolPtr
4907
testStorageVolLookupByKey(virConnectPtr conn,
4908 4909
                          const char *key)
{
4910
    testDriverPtr privconn = conn->privateData;
4911
    size_t i;
4912
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4913

4914
    testDriverLock(privconn);
4915
    for (i = 0; i < privconn->pools.count; i++) {
4916
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4917
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4918
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4919 4920
                virStorageVolDefFindByKey(privconn->pools.objs[i], key);

4921 4922 4923 4924
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
4925 4926
                                       privvol->key,
                                       NULL, NULL);
4927
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
4928 4929
                break;
            }
C
Cole Robinson 已提交
4930
        }
4931
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4932
    }
4933
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4934

4935
    if (!ret)
4936 4937
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching key '%s'"), key);
4938 4939

    return ret;
C
Cole Robinson 已提交
4940 4941 4942
}

static virStorageVolPtr
4943
testStorageVolLookupByPath(virConnectPtr conn,
4944 4945
                           const char *path)
{
4946
    testDriverPtr privconn = conn->privateData;
4947
    size_t i;
4948
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4949

4950
    testDriverLock(privconn);
4951
    for (i = 0; i < privconn->pools.count; i++) {
4952
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4953
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4954
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4955 4956
                virStorageVolDefFindByPath(privconn->pools.objs[i], path);

4957 4958 4959 4960
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
4961 4962
                                       privvol->key,
                                       NULL, NULL);
4963
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
4964 4965
                break;
            }
C
Cole Robinson 已提交
4966
        }
4967
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4968
    }
4969
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4970

4971
    if (!ret)
4972 4973
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching path '%s'"), path);
4974 4975

    return ret;
C
Cole Robinson 已提交
4976 4977 4978
}

static virStorageVolPtr
4979 4980 4981
testStorageVolCreateXML(virStoragePoolPtr pool,
                        const char *xmldesc,
                        unsigned int flags)
E
Eric Blake 已提交
4982
{
4983
    testDriverPtr privconn = pool->conn->privateData;
4984
    virStoragePoolObjPtr privpool;
4985 4986
    virStorageVolDefPtr privvol = NULL;
    virStorageVolPtr ret = NULL;
4987

E
Eric Blake 已提交
4988 4989
    virCheckFlags(0, NULL);

4990
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4991
        goto cleanup;
4992 4993

    if (!virStoragePoolObjIsActive(privpool)) {
4994 4995
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4996
        goto cleanup;
4997
    }
C
Cole Robinson 已提交
4998

4999
    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
5000
    if (privvol == NULL)
5001
        goto cleanup;
5002 5003

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
5004 5005
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
5006
        goto cleanup;
C
Cole Robinson 已提交
5007 5008 5009
    }

    /* Make sure enough space */
5010
    if ((privpool->def->allocation + privvol->target.allocation) >
C
Cole Robinson 已提交
5011
         privpool->def->capacity) {
5012 5013 5014
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
5015
        goto cleanup;
C
Cole Robinson 已提交
5016 5017
    }

5018 5019
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
5020
                    privvol->name) == -1)
5021
        goto cleanup;
C
Cole Robinson 已提交
5022

5023 5024 5025
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
        VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
                                privpool->volumes.count, privvol) < 0)
5026
        goto cleanup;
C
Cole Robinson 已提交
5027

5028
    privpool->def->allocation += privvol->target.allocation;
C
Cole Robinson 已提交
5029 5030 5031
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

5032
    ret = virGetStorageVol(pool->conn, privpool->def->name,
5033 5034
                           privvol->name, privvol->key,
                           NULL, NULL);
5035
    privvol = NULL;
5036

5037
 cleanup:
5038
    virStorageVolDefFree(privvol);
5039 5040
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5041
    return ret;
C
Cole Robinson 已提交
5042 5043
}

5044
static virStorageVolPtr
5045 5046 5047 5048
testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
                            const char *xmldesc,
                            virStorageVolPtr clonevol,
                            unsigned int flags)
E
Eric Blake 已提交
5049
{
5050
    testDriverPtr privconn = pool->conn->privateData;
5051 5052 5053 5054
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol = NULL, origvol = NULL;
    virStorageVolPtr ret = NULL;

E
Eric Blake 已提交
5055 5056
    virCheckFlags(0, NULL);

5057
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
5058 5059 5060
        goto cleanup;

    if (!virStoragePoolObjIsActive(privpool)) {
5061 5062
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
5063 5064 5065
        goto cleanup;
    }

5066
    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
5067 5068 5069 5070
    if (privvol == NULL)
        goto cleanup;

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
5071 5072
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
5073 5074 5075 5076 5077
        goto cleanup;
    }

    origvol = virStorageVolDefFindByName(privpool, clonevol->name);
    if (!origvol) {
5078 5079 5080
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       clonevol->name);
5081 5082 5083 5084
        goto cleanup;
    }

    /* Make sure enough space */
5085
    if ((privpool->def->allocation + privvol->target.allocation) >
5086
         privpool->def->capacity) {
5087 5088 5089
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
5090 5091 5092 5093 5094
        goto cleanup;
    }
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

5095 5096
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
5097
                    privvol->name) == -1)
5098 5099
        goto cleanup;

5100 5101 5102
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
        VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
                                privpool->volumes.count, privvol) < 0)
5103 5104
        goto cleanup;

5105
    privpool->def->allocation += privvol->target.allocation;
5106 5107 5108 5109
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    ret = virGetStorageVol(pool->conn, privpool->def->name,
5110 5111
                           privvol->name, privvol->key,
                           NULL, NULL);
5112 5113
    privvol = NULL;

5114
 cleanup:
5115 5116 5117 5118 5119 5120
    virStorageVolDefFree(privvol);
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    return ret;
}

C
Cole Robinson 已提交
5121
static int
5122 5123
testStorageVolDelete(virStorageVolPtr vol,
                     unsigned int flags)
E
Eric Blake 已提交
5124
{
5125
    testDriverPtr privconn = vol->conn->privateData;
5126 5127
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5128
    size_t i;
5129
    int ret = -1;
C
Cole Robinson 已提交
5130

E
Eric Blake 已提交
5131 5132
    virCheckFlags(0, -1);

5133
    if (!(privpool = testStoragePoolObjFindByName(privconn, vol->pool)))
5134
        goto cleanup;
5135 5136 5137 5138

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

    if (privvol == NULL) {
5139 5140 5141
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5142
        goto cleanup;
5143 5144 5145
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5146 5147
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5148
        goto cleanup;
5149 5150 5151
    }


5152
    privpool->def->allocation -= privvol->target.allocation;
C
Cole Robinson 已提交
5153 5154 5155
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

5156
    for (i = 0; i < privpool->volumes.count; i++) {
C
Cole Robinson 已提交
5157 5158 5159
        if (privpool->volumes.objs[i] == privvol) {
            virStorageVolDefFree(privvol);

5160
            VIR_DELETE_ELEMENT(privpool->volumes.objs, i, privpool->volumes.count);
C
Cole Robinson 已提交
5161 5162 5163
            break;
        }
    }
5164
    ret = 0;
C
Cole Robinson 已提交
5165

5166
 cleanup:
5167 5168
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5169
    return ret;
C
Cole Robinson 已提交
5170 5171 5172
}


5173 5174
static int testStorageVolumeTypeForPool(int pooltype)
{
C
Cole Robinson 已提交
5175

5176
    switch (pooltype) {
C
Cole Robinson 已提交
5177 5178 5179 5180 5181 5182 5183 5184 5185 5186
        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
5187
testStorageVolGetInfo(virStorageVolPtr vol,
5188 5189
                      virStorageVolInfoPtr info)
{
5190
    testDriverPtr privconn = vol->conn->privateData;
5191 5192
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5193
    int ret = -1;
5194

5195
    if (!(privpool = testStoragePoolObjFindByName(privconn, vol->pool)))
5196
        goto cleanup;
5197 5198 5199 5200

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

    if (privvol == NULL) {
5201 5202 5203
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5204
        goto cleanup;
5205 5206 5207
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5208 5209
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5210
        goto cleanup;
5211
    }
C
Cole Robinson 已提交
5212 5213 5214

    memset(info, 0, sizeof(*info));
    info->type = testStorageVolumeTypeForPool(privpool->def->type);
5215 5216
    info->capacity = privvol->target.capacity;
    info->allocation = privvol->target.allocation;
5217
    ret = 0;
C
Cole Robinson 已提交
5218

5219
 cleanup:
5220 5221
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5222
    return ret;
C
Cole Robinson 已提交
5223 5224 5225
}

static char *
5226 5227
testStorageVolGetXMLDesc(virStorageVolPtr vol,
                         unsigned int flags)
E
Eric Blake 已提交
5228
{
5229
    testDriverPtr privconn = vol->conn->privateData;
5230 5231
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5232
    char *ret = NULL;
5233

E
Eric Blake 已提交
5234 5235
    virCheckFlags(0, NULL);

5236
    if (!(privpool = testStoragePoolObjFindByName(privconn, vol->pool)))
5237
        goto cleanup;
5238 5239 5240 5241

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

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

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

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

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

static char *
5263 5264
testStorageVolGetPath(virStorageVolPtr vol)
{
5265
    testDriverPtr privconn = vol->conn->privateData;
5266 5267
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5268
    char *ret = NULL;
5269

5270
    if (!(privpool = testStoragePoolObjFindByName(privconn, vol->pool)))
5271
        goto cleanup;
5272 5273 5274 5275

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

    if (privvol == NULL) {
5276 5277 5278
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5279
        goto cleanup;
5280 5281 5282
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5283 5284
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5285
        goto cleanup;
5286 5287
    }

5288
    ignore_value(VIR_STRDUP(ret, privvol->target.path));
5289

5290
 cleanup:
5291 5292
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
5293 5294 5295
    return ret;
}

5296

5297
/* Node device implementations */
5298

5299 5300 5301 5302 5303 5304 5305
static virNodeDeviceObjPtr
testNodeDeviceObjFindByName(testDriverPtr driver,
                            const char *name)
{
    virNodeDeviceObjPtr obj;

    testDriverLock(driver);
5306
    obj = virNodeDeviceObjFindByName(driver->devs, name);
5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317
    testDriverUnlock(driver);

    if (!obj)
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       name);

    return obj;
}


5318 5319 5320
static int
testNodeNumOfDevices(virConnectPtr conn,
                     const char *cap,
E
Eric Blake 已提交
5321
                     unsigned int flags)
5322
{
5323
    testDriverPtr driver = conn->privateData;
5324 5325
    int ndevs = 0;

E
Eric Blake 已提交
5326 5327
    virCheckFlags(0, -1);

5328
    testDriverLock(driver);
5329
    ndevs = virNodeDeviceObjNumOfDevices(driver->devs, conn, cap, NULL);
5330 5331 5332 5333 5334
    testDriverUnlock(driver);

    return ndevs;
}

5335

5336 5337 5338 5339 5340
static int
testNodeListDevices(virConnectPtr conn,
                    const char *cap,
                    char **const names,
                    int maxnames,
E
Eric Blake 已提交
5341
                    unsigned int flags)
5342
{
5343
    testDriverPtr driver = conn->privateData;
5344
    int nnames = 0;
5345

E
Eric Blake 已提交
5346 5347
    virCheckFlags(0, -1);

5348
    testDriverLock(driver);
5349
    nnames = virNodeDeviceObjGetNames(driver->devs, conn, NULL,
5350
                                     cap, names, maxnames);
5351 5352
    testDriverUnlock(driver);

5353
    return nnames;
5354 5355
}

5356

5357 5358 5359
static virNodeDevicePtr
testNodeDeviceLookupByName(virConnectPtr conn, const char *name)
{
5360
    testDriverPtr driver = conn->privateData;
5361
    virNodeDeviceObjPtr obj;
5362
    virNodeDeviceDefPtr def;
5363 5364
    virNodeDevicePtr ret = NULL;

5365
    if (!(obj = testNodeDeviceObjFindByName(driver, name)))
5366
        return NULL;
5367
    def = virNodeDeviceObjGetDef(obj);
5368

5369
    if ((ret = virGetNodeDevice(conn, name))) {
5370
        if (VIR_STRDUP(ret->parent, def->parent) < 0) {
5371
            virObjectUnref(ret);
5372 5373
            ret = NULL;
        }
5374
    }
5375

5376
    virNodeDeviceObjUnlock(obj);
5377 5378 5379 5380
    return ret;
}

static char *
5381
testNodeDeviceGetXMLDesc(virNodeDevicePtr dev,
E
Eric Blake 已提交
5382
                         unsigned int flags)
5383
{
5384
    testDriverPtr driver = dev->conn->privateData;
5385 5386 5387
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

E
Eric Blake 已提交
5388 5389
    virCheckFlags(0, NULL);

5390
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5391
        return NULL;
5392

5393
    ret = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(obj));
5394

5395
    virNodeDeviceObjUnlock(obj);
5396 5397 5398 5399 5400 5401
    return ret;
}

static char *
testNodeDeviceGetParent(virNodeDevicePtr dev)
{
5402
    testDriverPtr driver = dev->conn->privateData;
5403
    virNodeDeviceObjPtr obj;
5404
    virNodeDeviceDefPtr def;
5405 5406
    char *ret = NULL;

5407
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5408
        return NULL;
5409
    def = virNodeDeviceObjGetDef(obj);
5410

5411 5412
    if (def->parent) {
        ignore_value(VIR_STRDUP(ret, def->parent));
5413
    } else {
5414 5415
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no parent for this device"));
5416 5417
    }

5418
    virNodeDeviceObjUnlock(obj);
5419 5420 5421
    return ret;
}

5422

5423 5424 5425
static int
testNodeDeviceNumOfCaps(virNodeDevicePtr dev)
{
5426
    testDriverPtr driver = dev->conn->privateData;
5427
    virNodeDeviceObjPtr obj;
5428
    virNodeDeviceDefPtr def;
5429 5430 5431
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;

5432
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5433
        return -1;
5434
    def = virNodeDeviceObjGetDef(obj);
5435

5436
    for (caps = def->caps; caps; caps = caps->next)
5437 5438
        ++ncaps;

5439 5440
    virNodeDeviceObjUnlock(obj);
    return ncaps;
5441 5442 5443 5444 5445 5446
}


static int
testNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
5447
    testDriverPtr driver = dev->conn->privateData;
5448
    virNodeDeviceObjPtr obj;
5449
    virNodeDeviceDefPtr def;
5450 5451 5452
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;

5453
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5454
        return -1;
5455
    def = virNodeDeviceObjGetDef(obj);
5456

5457
    for (caps = def->caps; caps && ncaps < maxnames; caps = caps->next) {
5458 5459 5460 5461
        if (VIR_STRDUP(names[ncaps],
                       virNodeDevCapTypeToString(caps->data.type)) < 0)
            goto error;
        ncaps++;
5462 5463
    }

5464 5465 5466 5467 5468 5469 5470 5471
    virNodeDeviceObjUnlock(obj);
    return ncaps;

 error:
    while (--ncaps >= 0)
        VIR_FREE(names[ncaps]);
    virNodeDeviceObjUnlock(obj);
    return -1;
5472 5473
}

5474

5475 5476
static virNodeDeviceObjPtr
testNodeDeviceMockCreateVport(testDriverPtr driver,
5477
                              const char *wwnn,
5478
                              const char *wwpn)
5479
{
5480 5481
    char *xml = NULL;
    virNodeDeviceDefPtr def = NULL;
5482
    virNodeDevCapsDefPtr caps;
5483
    virNodeDeviceObjPtr obj = NULL, objcopy = NULL;
5484
    virNodeDeviceDefPtr objdef;
5485
    virObjectEventPtr event = NULL;
5486

5487 5488 5489 5490 5491 5492 5493 5494 5495
    /* In the real code, we'd call virVHBAManageVport which would take the
     * wwnn/wwpn from the input XML in order to call the "vport_create"
     * function for the parent. That in turn would set off a sequence of
     * events resulting in the creation of a vHBA scsi_hostN in the
     * node device objects list using the "next" host number with the
     * wwnn/wwpn from the input XML. The following will mock this by
     * using the scsi_host11 definition, changing the name and the
     * scsi_host capability fields before calling virNodeDeviceAssignDef
     * to add the def to the node device objects list. */
5496
    if (!(objcopy = virNodeDeviceObjFindByName(driver->devs, "scsi_host11")))
5497 5498
        goto cleanup;

5499
    xml = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(objcopy));
5500 5501 5502 5503 5504
    virNodeDeviceObjUnlock(objcopy);
    if (!xml)
        goto cleanup;

    if (!(def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL)))
5505 5506
        goto cleanup;

5507
    VIR_FREE(def->name);
5508
    if (VIR_STRDUP(def->name, "scsi_host12") < 0)
5509 5510
        goto cleanup;

5511 5512 5513
    /* Find the 'scsi_host' cap and alter the host # and unique_id and
     * then for the 'fc_host' capability modify the wwnn/wwpn to be that
     * of the input XML. */
5514 5515
    caps = def->caps;
    while (caps) {
5516
        if (caps->data.type != VIR_NODE_DEV_CAP_SCSI_HOST)
5517 5518
            continue;

5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532
        /* For the "fc_host" cap - change the wwnn/wwpn to match the input */
        if (caps->data.scsi_host.flags & VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST) {
            VIR_FREE(caps->data.scsi_host.wwnn);
            VIR_FREE(caps->data.scsi_host.wwpn);
            if (VIR_STRDUP(caps->data.scsi_host.wwnn, wwnn) < 0 ||
                VIR_STRDUP(caps->data.scsi_host.wwpn, wwpn) < 0)
                goto cleanup;
        } else {
            /* For the "scsi_host" cap, increment our host and unique_id to
             * give the appearance that something new was created - then add
             * that to the node device driver */
            caps->data.scsi_host.host++;
            caps->data.scsi_host.unique_id++;
        }
5533 5534 5535
        caps = caps->next;
    }

5536
    if (!(obj = virNodeDeviceObjAssignDef(driver->devs, def)))
5537
        goto cleanup;
5538
    def = NULL;
5539
    objdef = virNodeDeviceObjGetDef(obj);
5540

5541
    event = virNodeDeviceEventLifecycleNew(objdef->name,
5542 5543
                                           VIR_NODE_DEVICE_EVENT_CREATED,
                                           0);
5544 5545 5546
    testObjectEventQueue(driver, event);

 cleanup:
5547
    VIR_FREE(xml);
5548 5549
    virNodeDeviceDefFree(def);
    return obj;
5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560
}


static virNodeDevicePtr
testNodeDeviceCreateXML(virConnectPtr conn,
                        const char *xmlDesc,
                        unsigned int flags)
{
    testDriverPtr driver = conn->privateData;
    virNodeDeviceDefPtr def = NULL;
    char *wwnn = NULL, *wwpn = NULL;
5561 5562
    virNodeDevicePtr dev = NULL, ret = NULL;
    virNodeDeviceObjPtr obj = NULL;
5563
    virNodeDeviceDefPtr objdef;
5564 5565 5566 5567 5568 5569 5570 5571

    virCheckFlags(0, NULL);

    testDriverLock(driver);

    if (!(def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, NULL)))
        goto cleanup;

5572 5573 5574
    /* We run this simply for validation - it essentially validates that
     * the input XML either has a wwnn/wwpn or virNodeDevCapSCSIHostParseXML
     * generated a wwnn/wwpn */
5575 5576 5577
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) < 0)
        goto cleanup;

5578 5579 5580
    /* Unlike the "real" code we don't need the parent_host in order to
     * call virVHBAManageVport, but still let's make sure the code finds
     * something valid and no one messed up the mock environment. */
5581
    if (virNodeDeviceObjGetParentHost(driver->devs, def, CREATE_DEVICE) < 0)
5582 5583 5584 5585
        goto cleanup;

    /* In the real code, we'd call virVHBAManageVport followed by
     * find_new_device, but we cannot do that here since we're not
5586 5587 5588
     * mocking udev. The mock routine will copy an existing vHBA and
     * rename a few fields to mock that. So in order to allow that to
     * work properly, we need to drop our lock */
5589 5590
    if (!(obj = testNodeDeviceMockCreateVport(driver, wwnn, wwpn)))
        goto cleanup;
5591
    objdef = virNodeDeviceObjGetDef(obj);
5592

5593
    if (!(dev = virGetNodeDevice(conn, objdef->name)))
5594 5595 5596 5597 5598 5599 5600 5601
        goto cleanup;

    VIR_FREE(dev->parent);
    if (VIR_STRDUP(dev->parent, def->parent) < 0)
        goto cleanup;

    ret = dev;
    dev = NULL;
5602

5603
 cleanup:
5604 5605
    if (obj)
        virNodeDeviceObjUnlock(obj);
5606
    testDriverUnlock(driver);
5607
    virNodeDeviceDefFree(def);
5608
    virObjectUnref(dev);
5609 5610
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
5611
    return ret;
5612 5613 5614 5615 5616 5617
}

static int
testNodeDeviceDestroy(virNodeDevicePtr dev)
{
    int ret = 0;
5618
    testDriverPtr driver = dev->conn->privateData;
5619
    virNodeDeviceObjPtr obj = NULL;
5620
    virNodeDeviceDefPtr def;
5621
    char *parent_name = NULL, *wwnn = NULL, *wwpn = NULL;
5622
    virObjectEventPtr event = NULL;
5623

5624
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5625
        return -1;
5626
    def = virNodeDeviceObjGetDef(obj);
5627

5628
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) == -1)
5629
        goto cleanup;
5630

5631
    if (VIR_STRDUP(parent_name, def->parent) < 0)
5632
        goto cleanup;
5633 5634 5635 5636 5637 5638 5639

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

5640 5641
    /* We do this just for basic validation, but also avoid finding a
     * vport capable HBA if for some reason our vHBA doesn't exist */
5642
    if (virNodeDeviceObjGetParentHost(driver->devs, def,
5643
                                      EXISTING_DEVICE) < 0) {
5644
        obj = NULL;
5645
        goto cleanup;
5646 5647
    }

5648 5649 5650 5651
    event = virNodeDeviceEventLifecycleNew(dev->name,
                                           VIR_NODE_DEVICE_EVENT_DELETED,
                                           0);

5652
    virNodeDeviceObjLock(obj);
5653
    virNodeDeviceObjRemove(driver->devs, obj);
5654 5655
    virNodeDeviceObjFree(obj);
    obj = NULL;
5656

5657
 cleanup:
5658 5659
    if (obj)
        virNodeDeviceObjUnlock(obj);
5660
    testObjectEventQueue(driver, event);
5661 5662 5663 5664 5665 5666
    VIR_FREE(parent_name);
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return ret;
}

5667 5668

/* Domain event implementations */
5669
static int
5670 5671 5672 5673
testConnectDomainEventRegister(virConnectPtr conn,
                               virConnectDomainEventCallback callback,
                               void *opaque,
                               virFreeCallback freecb)
5674
{
5675
    testDriverPtr driver = conn->privateData;
5676
    int ret = 0;
5677

5678
    if (virDomainEventStateRegister(conn, driver->eventState,
5679 5680
                                    callback, opaque, freecb) < 0)
        ret = -1;
5681 5682 5683 5684

    return ret;
}

5685

5686
static int
5687 5688
testConnectDomainEventDeregister(virConnectPtr conn,
                                 virConnectDomainEventCallback callback)
5689
{
5690
    testDriverPtr driver = conn->privateData;
5691
    int ret = 0;
5692

5693
    if (virDomainEventStateDeregister(conn, driver->eventState,
5694 5695
                                      callback) < 0)
        ret = -1;
5696 5697 5698 5699

    return ret;
}

5700 5701

static int
5702 5703 5704 5705 5706 5707
testConnectDomainEventRegisterAny(virConnectPtr conn,
                                  virDomainPtr dom,
                                  int eventID,
                                  virConnectDomainEventGenericCallback callback,
                                  void *opaque,
                                  virFreeCallback freecb)
5708
{
5709
    testDriverPtr driver = conn->privateData;
5710 5711
    int ret;

5712
    if (virDomainEventStateRegisterID(conn, driver->eventState,
5713 5714
                                      dom, eventID,
                                      callback, opaque, freecb, &ret) < 0)
5715
        ret = -1;
5716 5717 5718 5719 5720

    return ret;
}

static int
5721 5722
testConnectDomainEventDeregisterAny(virConnectPtr conn,
                                    int callbackID)
5723
{
5724
    testDriverPtr driver = conn->privateData;
5725
    int ret = 0;
5726

5727
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5728
                                        callbackID, true) < 0)
5729
        ret = -1;
5730 5731 5732 5733 5734

    return ret;
}


5735 5736 5737 5738 5739 5740 5741 5742
static int
testConnectNetworkEventRegisterAny(virConnectPtr conn,
                                   virNetworkPtr net,
                                   int eventID,
                                   virConnectNetworkEventGenericCallback callback,
                                   void *opaque,
                                   virFreeCallback freecb)
{
5743
    testDriverPtr driver = conn->privateData;
5744 5745
    int ret;

5746
    if (virNetworkEventStateRegisterID(conn, driver->eventState,
5747
                                       net, eventID, callback,
5748 5749 5750 5751 5752 5753 5754 5755 5756 5757
                                       opaque, freecb, &ret) < 0)
        ret = -1;

    return ret;
}

static int
testConnectNetworkEventDeregisterAny(virConnectPtr conn,
                                     int callbackID)
{
5758
    testDriverPtr driver = conn->privateData;
5759
    int ret = 0;
5760

5761
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5762
                                        callbackID, true) < 0)
5763
        ret = -1;
5764 5765 5766 5767

    return ret;
}

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
static int
testConnectStoragePoolEventRegisterAny(virConnectPtr conn,
                                       virStoragePoolPtr pool,
                                       int eventID,
                                       virConnectStoragePoolEventGenericCallback callback,
                                       void *opaque,
                                       virFreeCallback freecb)
{
    testDriverPtr driver = conn->privateData;
    int ret;

    if (virStoragePoolEventStateRegisterID(conn, driver->eventState,
                                           pool, eventID, callback,
                                           opaque, freecb, &ret) < 0)
        ret = -1;

    return ret;
}

static int
testConnectStoragePoolEventDeregisterAny(virConnectPtr conn,
                                         int callbackID)
{
    testDriverPtr driver = conn->privateData;
    int ret = 0;

    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5795
                                        callbackID, true) < 0)
5796 5797 5798 5799 5800
        ret = -1;

    return ret;
}

5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827
static int
testConnectNodeDeviceEventRegisterAny(virConnectPtr conn,
                                      virNodeDevicePtr dev,
                                      int eventID,
                                      virConnectNodeDeviceEventGenericCallback callback,
                                      void *opaque,
                                      virFreeCallback freecb)
{
    testDriverPtr driver = conn->privateData;
    int ret;

    if (virNodeDeviceEventStateRegisterID(conn, driver->eventState,
                                          dev, eventID, callback,
                                          opaque, freecb, &ret) < 0)
        ret = -1;

    return ret;
}

static int
testConnectNodeDeviceEventDeregisterAny(virConnectPtr conn,
                                        int callbackID)
{
    testDriverPtr driver = conn->privateData;
    int ret = 0;

    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5828
                                        callbackID, true) < 0)
5829 5830 5831 5832 5833
        ret = -1;

    return ret;
}

5834 5835 5836
static int testConnectListAllDomains(virConnectPtr conn,
                                     virDomainPtr **domains,
                                     unsigned int flags)
5837
{
5838
    testDriverPtr privconn = conn->privateData;
5839

O
Osier Yang 已提交
5840
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
5841

5842 5843
    return virDomainObjListExport(privconn->domains, conn, domains,
                                  NULL, flags);
5844 5845
}

5846
static int
P
Peter Krempa 已提交
5847
testNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,
5848 5849 5850 5851 5852 5853 5854
                  unsigned char **cpumap,
                  unsigned int *online,
                  unsigned int flags)
{
    virCheckFlags(0, -1);

    if (cpumap) {
5855
        if (VIR_ALLOC_N(*cpumap, 1) < 0)
P
Peter Krempa 已提交
5856
            return -1;
5857 5858 5859 5860 5861 5862
        *cpumap[0] = 0x15;
    }

    if (online)
        *online = 3;

P
Peter Krempa 已提交
5863
    return  8;
5864 5865
}

5866 5867 5868 5869 5870 5871 5872 5873 5874 5875
static char *
testDomainScreenshot(virDomainPtr dom ATTRIBUTE_UNUSED,
                     virStreamPtr st,
                     unsigned int screen ATTRIBUTE_UNUSED,
                     unsigned int flags)
{
    char *ret = NULL;

    virCheckFlags(0, NULL);

5876
    if (VIR_STRDUP(ret, "image/png") < 0)
5877 5878
        return NULL;

D
Daniel P. Berrange 已提交
5879
    if (virFDStreamOpenFile(st, PKGDATADIR "/test-screenshot.png", 0, 0, O_RDONLY) < 0)
5880 5881 5882 5883 5884
        VIR_FREE(ret);

    return ret;
}

5885 5886
static int
testConnectGetCPUModelNames(virConnectPtr conn ATTRIBUTE_UNUSED,
J
Jiri Denemark 已提交
5887
                            const char *archName,
5888 5889 5890
                            char ***models,
                            unsigned int flags)
{
J
Jiri Denemark 已提交
5891 5892
    virArch arch;

5893
    virCheckFlags(0, -1);
J
Jiri Denemark 已提交
5894 5895 5896 5897 5898 5899 5900 5901

    if (!(arch = virArchFromString(archName))) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("cannot find architecture %s"),
                       archName);
        return -1;
    }

J
Jiri Denemark 已提交
5902
    return virCPUGetModels(arch, models);
5903
}
5904

C
Cole Robinson 已提交
5905 5906 5907
static int
testDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
5908
    testDriverPtr privconn = dom->conn->privateData;
C
Cole Robinson 已提交
5909
    virDomainObjPtr vm = NULL;
5910
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
5911 5912 5913 5914 5915 5916
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
                  VIR_DOMAIN_SAVE_RUNNING |
                  VIR_DOMAIN_SAVE_PAUSED, -1);

5917 5918
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932

    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);
5933
    event = virDomainEventLifecycleNewFromObj(vm,
C
Cole Robinson 已提交
5934 5935 5936 5937 5938
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
    vm->hasManagedSave = true;

    ret = 0;
5939
 cleanup:
5940
    virDomainObjEndAPI(&vm);
5941
    testObjectEventQueue(privconn, event);
C
Cole Robinson 已提交
5942 5943 5944 5945 5946 5947 5948 5949 5950

    return ret;
}


static int
testDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm;
5951
    int ret;
C
Cole Robinson 已提交
5952 5953 5954

    virCheckFlags(0, -1);

5955 5956
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5957 5958

    ret = vm->hasManagedSave;
5959

5960
    virDomainObjEndAPI(&vm);
C
Cole Robinson 已提交
5961 5962 5963 5964 5965 5966 5967 5968 5969 5970
    return ret;
}

static int
testDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm;

    virCheckFlags(0, -1);

5971 5972
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5973 5974

    vm->hasManagedSave = false;
5975

5976
    virDomainObjEndAPI(&vm);
5977
    return 0;
C
Cole Robinson 已提交
5978 5979 5980
}


5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014
/*
 * 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;
6015
    int n;
6016 6017 6018 6019 6020

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6021
        return -1;
6022 6023 6024

    n = virDomainSnapshotObjListNum(vm->snapshots, NULL, flags);

6025
    virDomainObjEndAPI(&vm);
6026 6027 6028 6029 6030 6031 6032 6033 6034 6035
    return n;
}

static int
testDomainSnapshotListNames(virDomainPtr domain,
                            char **names,
                            int nameslen,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6036
    int n;
6037 6038 6039 6040 6041

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6042
        return -1;
6043 6044 6045 6046

    n = virDomainSnapshotObjListGetNames(vm->snapshots, NULL, names, nameslen,
                                         flags);

6047
    virDomainObjEndAPI(&vm);
6048 6049 6050 6051 6052 6053 6054 6055 6056
    return n;
}

static int
testDomainListAllSnapshots(virDomainPtr domain,
                           virDomainSnapshotPtr **snaps,
                           unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6057
    int n;
6058 6059 6060 6061 6062

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6063
        return -1;
6064 6065 6066

    n = virDomainListSnapshots(vm->snapshots, NULL, domain, snaps, flags);

6067
    virDomainObjEndAPI(&vm);
6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084
    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)))
6085
        return -1;
6086 6087 6088 6089 6090 6091 6092

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    n = virDomainSnapshotObjListGetNames(vm->snapshots, snap, names, nameslen,
                                         flags);

6093
 cleanup:
6094
    virDomainObjEndAPI(&vm);
6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109
    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)))
6110
        return -1;
6111 6112 6113 6114 6115 6116

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    n = virDomainSnapshotObjListNum(vm->snapshots, snap, flags);

6117
 cleanup:
6118
    virDomainObjEndAPI(&vm);
6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134
    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)))
6135
        return -1;
6136 6137 6138 6139 6140 6141 6142

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    n = virDomainListSnapshots(vm->snapshots, snap, snapshot->domain, snaps,
                               flags);

6143
 cleanup:
6144
    virDomainObjEndAPI(&vm);
6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159
    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)))
6160
        return NULL;
6161 6162 6163 6164 6165 6166

    if (!(snap = testSnapObjFromName(vm, name)))
        goto cleanup;

    snapshot = virGetDomainSnapshot(domain, snap->def->name);

6167
 cleanup:
6168
    virDomainObjEndAPI(&vm);
6169 6170 6171 6172 6173 6174 6175 6176
    return snapshot;
}

static int
testDomainHasCurrentSnapshot(virDomainPtr domain,
                             unsigned int flags)
{
    virDomainObjPtr vm;
6177
    int ret;
6178 6179 6180 6181

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6182
        return -1;
6183 6184 6185

    ret = (vm->current_snapshot != NULL);

6186
    virDomainObjEndAPI(&vm);
6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200
    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)))
6201
        return NULL;
6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214

    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);

6215
 cleanup:
6216
    virDomainObjEndAPI(&vm);
6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229
    return parent;
}

static virDomainSnapshotPtr
testDomainSnapshotCurrent(virDomainPtr domain,
                          unsigned int flags)
{
    virDomainObjPtr vm;
    virDomainSnapshotPtr snapshot = NULL;

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
6230
        return NULL;
6231 6232 6233 6234 6235 6236 6237 6238 6239

    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);

6240
 cleanup:
6241
    virDomainObjEndAPI(&vm);
6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252
    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];
6253
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6254 6255 6256 6257

    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6258
        return NULL;
6259 6260 6261 6262 6263 6264

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    virUUIDFormat(snapshot->domain->uuid, uuidstr);

6265
    xml = virDomainSnapshotDefFormat(uuidstr, snap->def, privconn->caps,
6266
                                     privconn->xmlopt,
6267 6268
                                     virDomainDefFormatConvertXMLFlags(flags),
                                     0);
6269

6270
 cleanup:
6271
    virDomainObjEndAPI(&vm);
6272 6273 6274 6275 6276 6277 6278 6279
    return xml;
}

static int
testDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6280
    int ret;
6281 6282 6283 6284

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6285
        return -1;
6286 6287 6288 6289

    ret = (vm->current_snapshot &&
           STREQ(snapshot->name, vm->current_snapshot->def->name));

6290
    virDomainObjEndAPI(&vm);
6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304
    return ret;
}


static int
testDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot,
                              unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6305
        return -1;
6306

C
Cole Robinson 已提交
6307
    if (!testSnapObjFromSnapshot(vm, snapshot))
6308 6309 6310 6311
        goto cleanup;

    ret = 1;

6312
 cleanup:
6313
    virDomainObjEndAPI(&vm);
6314 6315 6316
    return ret;
}

6317 6318 6319 6320 6321 6322
static int
testDomainSnapshotAlignDisks(virDomainObjPtr vm,
                             virDomainSnapshotDefPtr def,
                             unsigned int flags)
{
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
E
Eric Blake 已提交
6323
    bool align_match = true;
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

    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)
{
6352
    testDriverPtr privconn = domain->conn->privateData;
6353 6354 6355 6356
    virDomainObjPtr vm = NULL;
    virDomainSnapshotDefPtr def = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr snapshot = NULL;
6357
    virObjectEventPtr event = NULL;
6358
    char *xml = NULL;
6359 6360
    bool update_current = true;
    bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
6361 6362 6363 6364 6365 6366 6367 6368
    unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;

    /*
     * DISK_ONLY: Not implemented yet
     * REUSE_EXT: Not implemented yet
     *
     * NO_METADATA: Explicitly not implemented
     *
6369
     * REDEFINE + CURRENT: Implemented
6370 6371 6372 6373 6374 6375
     * HALT: Implemented
     * QUIESCE: Nothing to do
     * ATOMIC: Nothing to do
     * LIVE: Nothing to do
     */
    virCheckFlags(
6376 6377
        VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
        VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
6378 6379 6380 6381 6382
        VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
        VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
        VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
        VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, NULL);

6383 6384 6385 6386 6387
    if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)))
        update_current = false;
    if (redefine)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;

6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402
    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,
                                                parse_flags)))
        goto cleanup;

6403
    if (redefine) {
C
Cole Robinson 已提交
6404
        if (virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
6405
                                          privconn->xmlopt,
C
Cole Robinson 已提交
6406
                                          &update_current, flags) < 0)
6407 6408 6409 6410 6411
            goto cleanup;
    } else {
        if (!(def->dom = virDomainDefCopy(vm->def,
                                          privconn->caps,
                                          privconn->xmlopt,
6412
                                          NULL,
6413 6414
                                          true)))
            goto cleanup;
6415

6416
        if (testDomainSnapshotAlignDisks(vm, def, flags) < 0)
6417 6418 6419
            goto cleanup;
    }

6420 6421 6422 6423
    if (!snap) {
        if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
            goto cleanup;
        def = NULL;
6424 6425
    }

6426 6427 6428 6429 6430 6431 6432 6433 6434 6435
    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);
6436
            event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
6437 6438 6439
                                    VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
        }
    }
6440 6441

    snapshot = virGetDomainSnapshot(domain, snap->def->name);
6442
 cleanup:
6443 6444 6445 6446
    VIR_FREE(xml);
    if (vm) {
        if (snapshot) {
            virDomainSnapshotObjPtr other;
6447 6448
            if (update_current)
                vm->current_snapshot = snap;
6449 6450 6451 6452 6453 6454 6455
            other = virDomainSnapshotFindByName(vm->snapshots,
                                                snap->def->parent);
            snap->parent = other;
            other->nchildren++;
            snap->sibling = other->first_child;
            other->first_child = snap;
        }
6456
        virDomainObjEndAPI(&vm);
6457
    }
6458
    testObjectEventQueue(privconn, event);
6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470
    virDomainSnapshotDefFree(def);
    return snapshot;
}


typedef struct _testSnapRemoveData testSnapRemoveData;
typedef testSnapRemoveData *testSnapRemoveDataPtr;
struct _testSnapRemoveData {
    virDomainObjPtr vm;
    bool current;
};

6471
static int
6472
testDomainSnapshotDiscardAll(void *payload,
6473 6474
                             const void *name ATTRIBUTE_UNUSED,
                             void *data)
6475 6476 6477 6478 6479 6480 6481
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapRemoveDataPtr curr = data;

    if (snap->def->current)
        curr->current = true;
    virDomainSnapshotObjListRemove(curr->vm->snapshots, snap);
6482
    return 0;
6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493
}

typedef struct _testSnapReparentData testSnapReparentData;
typedef testSnapReparentData *testSnapReparentDataPtr;
struct _testSnapReparentData {
    virDomainSnapshotObjPtr parent;
    virDomainObjPtr vm;
    int err;
    virDomainSnapshotObjPtr last;
};

6494
static int
6495 6496 6497 6498 6499 6500 6501
testDomainSnapshotReparentChildren(void *payload,
                                   const void *name ATTRIBUTE_UNUSED,
                                   void *data)
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapReparentDataPtr rep = data;

6502
    if (rep->err < 0)
6503
        return 0;
6504 6505 6506 6507 6508 6509 6510

    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;
6511
        return 0;
6512 6513 6514 6515
    }

    if (!snap->sibling)
        rep->last = snap;
6516
    return 0;
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
}

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) {
6546
            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)
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
                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;
6590
 cleanup:
6591
    virDomainObjEndAPI(&vm);
6592 6593 6594 6595 6596 6597 6598
    return ret;
}

static int
testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                           unsigned int flags)
{
6599
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6600 6601
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
6602 6603
    virObjectEventPtr event = NULL;
    virObjectEventPtr event2 = NULL;
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 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666
    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;

    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;
6667 6668
    config = virDomainDefCopy(snap->def->dom, privconn->caps,
                              privconn->xmlopt, NULL, true);
6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680
    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.  */
6681 6682
            if (!virDomainDefCheckABIStability(vm->def, config,
                                               privconn->xmlopt)) {
6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695
                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);
6696
                event = virDomainEventLifecycleNewFromObj(vm,
6697 6698
                            VIR_DOMAIN_EVENT_STOPPED,
                            VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
6699
                testObjectEventQueue(privconn, event);
6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710
                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. */
6711
                event = virDomainEventLifecycleNewFromObj(vm,
6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724
                                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;
6725
            event = virDomainEventLifecycleNewFromObj(vm,
6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738
                                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 */
6739
                event2 = virDomainEventLifecycleNewFromObj(vm,
6740 6741 6742 6743 6744
                                VIR_DOMAIN_EVENT_SUSPENDED,
                                VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
            } /* else transition 6 and 9 use event as-is */
        } else {
            /* Transitions 2, 5, 8 */
C
Cédric Bosdonnat 已提交
6745
            virObjectUnref(event);
6746 6747 6748 6749
            event = NULL;

            if (was_stopped) {
                /* Transition 2 */
6750
                event = virDomainEventLifecycleNewFromObj(vm,
6751 6752 6753 6754
                                VIR_DOMAIN_EVENT_STARTED,
                                VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            } else if (was_running) {
                /* Transition 8 */
6755
                event = virDomainEventLifecycleNewFromObj(vm,
6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767
                                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);
6768
            event = virDomainEventLifecycleNewFromObj(vm,
6769 6770 6771 6772 6773 6774 6775 6776 6777
                                    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;

6778
            testObjectEventQueue(privconn, event);
6779
            event = virDomainEventLifecycleNewFromObj(vm,
6780 6781 6782
                            VIR_DOMAIN_EVENT_STARTED,
                            VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            if (paused) {
6783
                event2 = virDomainEventLifecycleNewFromObj(vm,
6784 6785 6786 6787 6788 6789 6790 6791
                                VIR_DOMAIN_EVENT_SUSPENDED,
                                VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
            }
        }
    }

    vm->current_snapshot = snap;
    ret = 0;
6792
 cleanup:
6793
    if (event) {
6794
        testObjectEventQueue(privconn, event);
6795
        testObjectEventQueue(privconn, event2);
C
Cole Robinson 已提交
6796
    } else {
C
Cédric Bosdonnat 已提交
6797
        virObjectUnref(event2);
6798
    }
6799
    virDomainObjEndAPI(&vm);
6800 6801 6802 6803 6804

    return ret;
}


6805

6806
static virHypervisorDriver testHypervisorDriver = {
6807
    .name = "Test",
6808 6809 6810
    .connectOpen = testConnectOpen, /* 0.1.1 */
    .connectClose = testConnectClose, /* 0.1.1 */
    .connectGetVersion = testConnectGetVersion, /* 0.1.1 */
6811
    .connectGetHostname = testConnectGetHostname, /* 0.6.3 */
6812
    .connectGetMaxVcpus = testConnectGetMaxVcpus, /* 0.3.2 */
6813
    .nodeGetInfo = testNodeGetInfo, /* 0.1.1 */
6814
    .nodeGetCPUStats = testNodeGetCPUStats, /* 2.3.0 */
6815
    .nodeGetFreeMemory = testNodeGetFreeMemory, /* 2.3.0 */
6816
    .nodeGetFreePages = testNodeGetFreePages, /* 2.3.0 */
6817
    .connectGetCapabilities = testConnectGetCapabilities, /* 0.2.1 */
6818
    .connectGetSysinfo = testConnectGetSysinfo, /* 2.3.0 */
6819
    .connectGetType = testConnectGetType, /* 2.3.0 */
6820 6821 6822
    .connectListDomains = testConnectListDomains, /* 0.1.1 */
    .connectNumOfDomains = testConnectNumOfDomains, /* 0.1.1 */
    .connectListAllDomains = testConnectListAllDomains, /* 0.9.13 */
6823
    .domainCreateXML = testDomainCreateXML, /* 0.1.4 */
6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837
    .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 */
6838 6839
    .domainGetState = testDomainGetState, /* 0.9.2 */
    .domainSave = testDomainSave, /* 0.3.2 */
6840
    .domainSaveFlags = testDomainSaveFlags, /* 0.9.4 */
6841
    .domainRestore = testDomainRestore, /* 0.3.2 */
6842
    .domainRestoreFlags = testDomainRestoreFlags, /* 0.9.4 */
6843
    .domainCoreDump = testDomainCoreDump, /* 0.3.2 */
6844
    .domainCoreDumpWithFormat = testDomainCoreDumpWithFormat, /* 1.2.3 */
6845
    .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */
6846 6847 6848 6849
    .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */
    .domainGetVcpusFlags = testDomainGetVcpusFlags, /* 0.8.5 */
    .domainPinVcpu = testDomainPinVcpu, /* 0.7.3 */
    .domainGetVcpus = testDomainGetVcpus, /* 0.7.3 */
6850
    .domainGetVcpuPinInfo = testDomainGetVcpuPinInfo, /* 1.2.18 */
6851 6852
    .domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
    .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
6853 6854
    .connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
    .connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
6855 6856 6857
    .domainCreate = testDomainCreate, /* 0.1.11 */
    .domainCreateWithFlags = testDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = testDomainDefineXML, /* 0.1.11 */
6858
    .domainDefineXMLFlags = testDomainDefineXMLFlags, /* 1.2.12 */
6859
    .domainUndefine = testDomainUndefine, /* 0.1.11 */
6860
    .domainUndefineFlags = testDomainUndefineFlags, /* 0.9.4 */
6861 6862 6863
    .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
    .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
    .domainGetSchedulerType = testDomainGetSchedulerType, /* 0.3.2 */
6864 6865 6866 6867
    .domainGetSchedulerParameters = testDomainGetSchedulerParameters, /* 0.3.2 */
    .domainGetSchedulerParametersFlags = testDomainGetSchedulerParametersFlags, /* 0.9.2 */
    .domainSetSchedulerParameters = testDomainSetSchedulerParameters, /* 0.3.2 */
    .domainSetSchedulerParametersFlags = testDomainSetSchedulerParametersFlags, /* 0.9.2 */
6868 6869 6870
    .domainBlockStats = testDomainBlockStats, /* 0.7.0 */
    .domainInterfaceStats = testDomainInterfaceStats, /* 0.7.0 */
    .nodeGetCellsFreeMemory = testNodeGetCellsFreeMemory, /* 0.4.2 */
6871 6872 6873 6874
    .connectDomainEventRegister = testConnectDomainEventRegister, /* 0.6.0 */
    .connectDomainEventDeregister = testConnectDomainEventDeregister, /* 0.6.0 */
    .connectIsEncrypted = testConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = testConnectIsSecure, /* 0.7.3 */
6875 6876 6877
    .domainIsActive = testDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = testDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = testDomainIsUpdated, /* 0.8.6 */
6878 6879 6880
    .connectDomainEventRegisterAny = testConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = testConnectDomainEventDeregisterAny, /* 0.8.0 */
    .connectIsAlive = testConnectIsAlive, /* 0.9.8 */
6881
    .nodeGetCPUMap = testNodeGetCPUMap, /* 1.0.0 */
6882
    .domainScreenshot = testDomainScreenshot, /* 1.0.5 */
6883 6884
    .domainGetMetadata = testDomainGetMetadata, /* 1.1.3 */
    .domainSetMetadata = testDomainSetMetadata, /* 1.1.3 */
6885
    .connectGetCPUModelNames = testConnectGetCPUModelNames, /* 1.1.3 */
6886 6887 6888 6889 6890 6891 6892 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902
    .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 */
6903 6904 6905
    .domainSnapshotCreateXML = testDomainSnapshotCreateXML, /* 1.1.4 */
    .domainRevertToSnapshot = testDomainRevertToSnapshot, /* 1.1.4 */
    .domainSnapshotDelete = testDomainSnapshotDelete, /* 1.1.4 */
6906

E
Eric Blake 已提交
6907
    .connectBaselineCPU = testConnectBaselineCPU, /* 1.2.0 */
6908 6909 6910
};

static virNetworkDriver testNetworkDriver = {
6911 6912 6913 6914 6915
    .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 */
6916 6917
    .connectNetworkEventRegisterAny = testConnectNetworkEventRegisterAny, /* 1.2.1 */
    .connectNetworkEventDeregisterAny = testConnectNetworkEventDeregisterAny, /* 1.2.1 */
6918 6919 6920 6921
    .networkLookupByUUID = testNetworkLookupByUUID, /* 0.3.2 */
    .networkLookupByName = testNetworkLookupByName, /* 0.3.2 */
    .networkCreateXML = testNetworkCreateXML, /* 0.3.2 */
    .networkDefineXML = testNetworkDefineXML, /* 0.3.2 */
6922
    .networkUndefine = testNetworkUndefine, /* 0.3.2 */
6923
    .networkUpdate = testNetworkUpdate, /* 0.10.2 */
6924
    .networkCreate = testNetworkCreate, /* 0.3.2 */
6925 6926 6927 6928 6929 6930 6931
    .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 */
6932 6933
};

L
Laine Stump 已提交
6934
static virInterfaceDriver testInterfaceDriver = {
6935 6936 6937 6938 6939 6940
    .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 */
6941 6942 6943 6944 6945 6946
    .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 */
6947 6948 6949
    .interfaceChangeBegin = testInterfaceChangeBegin,   /* 0.9.2 */
    .interfaceChangeCommit = testInterfaceChangeCommit,  /* 0.9.2 */
    .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */
L
Laine Stump 已提交
6950 6951 6952
};


6953
static virStorageDriver testStorageDriver = {
6954 6955 6956 6957 6958 6959
    .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 */
6960 6961
    .connectStoragePoolEventRegisterAny = testConnectStoragePoolEventRegisterAny, /* 2.0.0 */
    .connectStoragePoolEventDeregisterAny = testConnectStoragePoolEventDeregisterAny, /* 2.0.0 */
6962 6963 6964
    .storagePoolLookupByName = testStoragePoolLookupByName, /* 0.5.0 */
    .storagePoolLookupByUUID = testStoragePoolLookupByUUID, /* 0.5.0 */
    .storagePoolLookupByVolume = testStoragePoolLookupByVolume, /* 0.5.0 */
6965 6966
    .storagePoolCreateXML = testStoragePoolCreateXML, /* 0.5.0 */
    .storagePoolDefineXML = testStoragePoolDefineXML, /* 0.5.0 */
6967 6968
    .storagePoolBuild = testStoragePoolBuild, /* 0.5.0 */
    .storagePoolUndefine = testStoragePoolUndefine, /* 0.5.0 */
6969
    .storagePoolCreate = testStoragePoolCreate, /* 0.5.0 */
6970 6971 6972 6973 6974 6975 6976
    .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 */
6977
    .storagePoolNumOfVolumes = testStoragePoolNumOfVolumes, /* 0.5.0 */
6978 6979 6980
    .storagePoolListVolumes = testStoragePoolListVolumes, /* 0.5.0 */
    .storagePoolListAllVolumes = testStoragePoolListAllVolumes, /* 0.10.2 */

6981 6982 6983 6984 6985 6986 6987 6988 6989
    .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 */
6990 6991
    .storagePoolIsActive = testStoragePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = testStoragePoolIsPersistent, /* 0.7.3 */
6992 6993
};

6994
static virNodeDeviceDriver testNodeDeviceDriver = {
6995 6996
    .connectNodeDeviceEventRegisterAny = testConnectNodeDeviceEventRegisterAny, /* 2.2.0 */
    .connectNodeDeviceEventDeregisterAny = testConnectNodeDeviceEventDeregisterAny, /* 2.2.0 */
6997 6998 6999 7000 7001 7002 7003 7004 7005
    .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 */
7006 7007
};

7008 7009 7010 7011 7012 7013 7014 7015
static virConnectDriver testConnectDriver = {
    .hypervisorDriver = &testHypervisorDriver,
    .interfaceDriver = &testInterfaceDriver,
    .networkDriver = &testNetworkDriver,
    .nodeDeviceDriver = &testNodeDeviceDriver,
    .nwfilterDriver = NULL,
    .secretDriver = NULL,
    .storageDriver = &testStorageDriver,
7016 7017
};

7018 7019 7020 7021 7022 7023 7024 7025
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
7026 7027
    return virRegisterConnectDriver(&testConnectDriver,
                                    false);
7028
}