test_driver.c 193.9 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 obj);
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
        virNetworkObjSetActive(obj, true);
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
    VIR_FREE(nodes);
    return ret;
}

1042

1043
static int
C
Cole Robinson 已提交
1044
testOpenVolumesForPool(const char *file,
1045
                       xmlXPathContextPtr ctxt,
1046 1047
                       virStoragePoolObjPtr obj,
                       int objidx)
1048 1049 1050 1051 1052 1053 1054 1055
{
    char *vol_xpath;
    size_t i;
    int num, ret = -1;
    xmlNodePtr *nodes = NULL;
    virStorageVolDefPtr def = NULL;

    /* Find storage volumes */
1056
    if (virAsprintf(&vol_xpath, "/node/pool[%d]/volume", objidx) < 0)
1057 1058 1059 1060
        goto error;

    num = virXPathNodeSet(vol_xpath, ctxt, &nodes);
    VIR_FREE(vol_xpath);
1061
    if (num < 0)
1062 1063 1064
        goto error;

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

1070
        def = virStorageVolDefParseNode(obj->def, ctxt->doc, node, 0);
C
Cole Robinson 已提交
1071 1072
        if (!def)
            goto error;
1073 1074 1075

        if (def->target.path == NULL) {
            if (virAsprintf(&def->target.path, "%s/%s",
1076
                            obj->def->target.path, def->name) < 0)
1077 1078 1079 1080 1081
                goto error;
        }

        if (!def->key && VIR_STRDUP(def->key, def->target.path) < 0)
            goto error;
1082
        if (VIR_APPEND_ELEMENT_COPY(obj->volumes.objs, obj->volumes.count, def) < 0)
1083
            goto error;
1084

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

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

1097

1098
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
    VIR_FREE(nodes);
    return ret;
}

1150

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

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

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

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

1176
        if (!(obj = virNodeDeviceObjListAssignDef(privconn->devs, def))) {
1177 1178 1179
            virNodeDeviceDefFree(def);
            goto error;
        }
1180

1181
        virNodeDeviceObjEndAPI(&obj);
1182 1183 1184
    }

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

1190
static int
1191
testParseAuthUsers(testDriverPtr privconn,
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 1224
                   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;
1225
 error:
1226 1227 1228
    VIR_FREE(nodes);
    return ret;
}
1229

C
Cole Robinson 已提交
1230 1231 1232 1233 1234
static int
testOpenParse(testDriverPtr privconn,
              const char *file,
              xmlXPathContextPtr ctxt)
{
1235
    if (!virXMLNodeNameEqual(ctxt->node, "node")) {
C
Cole Robinson 已提交
1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260
        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;
}

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

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

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

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

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

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

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

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

1292
    return 0;
1293 1294

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

1302 1303 1304 1305 1306 1307 1308
/* 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;
1309 1310
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
1311
    size_t i;
1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328

    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;
1329 1330 1331 1332
    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;
1333
    }
1334
    for (i = 0; i < 16; i++) {
1335 1336 1337
        virBitmapPtr siblings = virBitmapNew(16);
        if (!siblings)
            goto error;
1338 1339 1340 1341 1342
        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;
1343 1344 1345 1346 1347
    }

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

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

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

    defaultConn = privconn;

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

    return VIR_DRV_OPEN_SUCCESS;

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

1373 1374 1375 1376
static int
testConnectAuthenticate(virConnectPtr conn,
                        virConnectAuthPtr auth)
{
1377
    testDriverPtr privconn = conn->privateData;
1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401
    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;

1402
 found_user:
1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421
    /* 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;
1422
 cleanup:
1423 1424 1425 1426
    VIR_FREE(username);
    VIR_FREE(password);
    return ret;
}
1427

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

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

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

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

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

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

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

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

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

1469
    return VIR_DRV_OPEN_SUCCESS;
1470 1471
}

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

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

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

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

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

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

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


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

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

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

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

1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546
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;
}

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

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

1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586
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;
}

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

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

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

1602
    return count;
1603 1604
}

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

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

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

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

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

    ret = obj->persistent;

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

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

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

1648 1649 1650
    virCheckFlags(VIR_DOMAIN_START_VALIDATE, NULL);

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1860 1861
    virCheckFlags(0, -1);

1862

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    virCheckFlags(0, -1);

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

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

2001
    virDomainObjEndAPI(&privdom);
2002 2003

    return 0;
2004 2005
}

2006 2007
#define TEST_SAVE_MAGIC "TestGuestMagic"

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

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

2027

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

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

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

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

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

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

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

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

2089
    ret = 0;
2090
 cleanup:
2091 2092 2093 2094
    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 已提交
2095
     * and have reported an earlier error */
2096
    if (ret != 0) {
2097
        VIR_FORCE_CLOSE(fd);
2098 2099
        unlink(path);
    }
2100
    virDomainObjEndAPI(&privdom);
2101
    testObjectEventQueue(privconn, event);
2102
    return ret;
2103 2104
}

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

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

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

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

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

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

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

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

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

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

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

2231

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

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

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

2260 2261 2262 2263 2264 2265 2266
    /* 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;
    }

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

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

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

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)
{
2298 2299 2300
    char *ret;

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

2304 2305 2306

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2452 2453
    ret = 0;

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

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

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

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

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

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

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

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

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

    virBitmapSetAll(allcpumap);

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

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

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

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

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

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

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

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

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

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

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

2558 2559
    def = privdom->def;

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

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

2574 2575 2576
    virBitmapFree(vcpuinfo->cpumask);

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

    ret = 0;
2580

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

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

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

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

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

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

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

2620 2621
    /* Flags checked by virDomainDefFormat */

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

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

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

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

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

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

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

2647
    testDriverPtr privconn = conn->privateData;
2648 2649

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

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

    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
2667

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

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

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

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

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

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

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

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

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

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, NULL);

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

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

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

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

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

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

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

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

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


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

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

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

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

2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837
#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;
}
2838

2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854
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;
}

2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878
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;
}

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

2886 2887
    virCheckFlags(0, -1);

2888
    testDriverLock(privconn);
2889

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

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

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

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

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

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

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

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

2933

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

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

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

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

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

2973
    ret = 0;
2974

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

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

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

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

2994
    *autostart = privdom->autostart;
2995

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


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

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

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

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

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

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

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

3025 3026 3027
    return type;
}

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

3037 3038
    virCheckFlags(0, -1);

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

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

    *nparams = 1;
3049 3050
    ret = 0;

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

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

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

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

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

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

3091 3092
    ret = 0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3211

3212 3213 3214 3215
static virNetworkObjPtr
testNetworkObjFindByUUID(testDriverPtr privconn,
                         const unsigned char *uuid)
{
3216
    virNetworkObjPtr obj;
3217 3218
    char uuidstr[VIR_UUID_STRING_BUFLEN];

3219
    if (!(obj = virNetworkObjFindByUUID(privconn->networks, uuid))) {
3220 3221 3222 3223 3224 3225
        virUUIDFormat(uuid, uuidstr);
        virReportError(VIR_ERR_NO_NETWORK,
                       _("no network with matching uuid '%s'"),
                       uuidstr);
    }

3226
    return obj;
3227 3228 3229
}


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

3239
    if (!(obj = testNetworkObjFindByUUID(privconn, uuid)))
3240
        goto cleanup;
3241
    def = virNetworkObjGetDef(obj);
3242

3243
    net = virGetNetwork(conn, def->name, def->uuid);
3244

3245
 cleanup:
3246 3247
    virNetworkObjEndAPI(&obj);
    return net;
3248
}
3249

3250 3251 3252 3253 3254

static virNetworkObjPtr
testNetworkObjFindByName(testDriverPtr privconn,
                         const char *name)
{
3255
    virNetworkObjPtr obj;
3256

3257
    if (!(obj = virNetworkObjFindByName(privconn->networks, name)))
3258 3259 3260 3261
        virReportError(VIR_ERR_NO_NETWORK,
                       _("no network with matching name '%s'"),
                       name);

3262
    return obj;
3263 3264 3265
}


3266 3267 3268
static virNetworkPtr
testNetworkLookupByName(virConnectPtr conn,
                        const char *name)
3269
{
3270
    testDriverPtr privconn = conn->privateData;
3271
    virNetworkObjPtr obj;
3272
    virNetworkDefPtr def;
3273
    virNetworkPtr net = NULL;
3274

3275
    if (!(obj = testNetworkObjFindByName(privconn, name)))
3276
        goto cleanup;
3277
    def = virNetworkObjGetDef(obj);
3278

3279
    net = virGetNetwork(conn, def->name, def->uuid);
3280

3281
 cleanup:
3282 3283
    virNetworkObjEndAPI(&obj);
    return net;
3284 3285 3286
}


3287 3288
static int
testConnectNumOfNetworks(virConnectPtr conn)
3289
{
3290
    testDriverPtr privconn = conn->privateData;
3291
    int numActive;
3292

3293 3294
    numActive = virNetworkObjListNumOfNetworks(privconn->networks,
                                               true, NULL, conn);
3295
    return numActive;
3296 3297
}

3298 3299 3300 3301 3302 3303

static int
testConnectListNetworks(virConnectPtr conn,
                        char **const names,
                        int nnames)
{
3304
    testDriverPtr privconn = conn->privateData;
3305
    int n;
3306

3307 3308
    n = virNetworkObjListGetNames(privconn->networks,
                                  true, names, nnames, NULL, conn);
3309
    return n;
3310 3311
}

3312 3313 3314

static int
testConnectNumOfDefinedNetworks(virConnectPtr conn)
3315
{
3316
    testDriverPtr privconn = conn->privateData;
3317
    int numInactive;
3318

3319 3320
    numInactive = virNetworkObjListNumOfNetworks(privconn->networks,
                                                 false, NULL, conn);
3321
    return numInactive;
3322 3323
}

3324 3325 3326 3327 3328 3329

static int
testConnectListDefinedNetworks(virConnectPtr conn,
                               char **const names,
                               int nnames)
{
3330
    testDriverPtr privconn = conn->privateData;
3331
    int n;
3332

3333 3334
    n = virNetworkObjListGetNames(privconn->networks,
                                  false, names, nnames, NULL, conn);
3335
    return n;
3336 3337
}

3338

3339
static int
3340
testConnectListAllNetworks(virConnectPtr conn,
3341 3342 3343
                           virNetworkPtr **nets,
                           unsigned int flags)
{
3344
    testDriverPtr privconn = conn->privateData;
3345 3346 3347

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

3348
    return virNetworkObjListExport(conn, privconn->networks, nets, NULL, flags);
3349
}
3350

3351 3352 3353

static int
testNetworkIsActive(virNetworkPtr net)
3354
{
3355
    testDriverPtr privconn = net->conn->privateData;
3356 3357 3358
    virNetworkObjPtr obj;
    int ret = -1;

3359
    if (!(obj = testNetworkObjFindByUUID(privconn, net->uuid)))
3360
        goto cleanup;
3361

3362 3363
    ret = virNetworkObjIsActive(obj);

3364
 cleanup:
3365
    virNetworkObjEndAPI(&obj);
3366 3367 3368
    return ret;
}

3369 3370 3371

static int
testNetworkIsPersistent(virNetworkPtr net)
3372
{
3373
    testDriverPtr privconn = net->conn->privateData;
3374 3375 3376
    virNetworkObjPtr obj;
    int ret = -1;

3377
    if (!(obj = testNetworkObjFindByUUID(privconn, net->uuid)))
3378
        goto cleanup;
3379

3380
    ret = virNetworkObjIsPersistent(obj);
3381

3382
 cleanup:
3383
    virNetworkObjEndAPI(&obj);
3384 3385 3386 3387
    return ret;
}


3388 3389
static virNetworkPtr
testNetworkCreateXML(virConnectPtr conn, const char *xml)
3390
{
3391
    testDriverPtr privconn = conn->privateData;
3392
    virNetworkDefPtr newDef;
3393
    virNetworkObjPtr obj = NULL;
3394
    virNetworkDefPtr def;
3395
    virNetworkPtr net = NULL;
3396
    virObjectEventPtr event = NULL;
3397

3398
    if ((newDef = virNetworkDefParseString(xml)) == NULL)
3399
        goto cleanup;
3400

3401
    if (!(obj = virNetworkObjAssignDef(privconn->networks, newDef,
3402 3403
                                       VIR_NETWORK_OBJ_LIST_ADD_LIVE |
                                       VIR_NETWORK_OBJ_LIST_ADD_CHECK_LIVE)))
3404
        goto cleanup;
3405 3406
    newDef = NULL;
    def = virNetworkObjGetDef(obj);
3407
    virNetworkObjSetActive(obj, true);
3408

3409
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
3410 3411
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3412

3413
    net = virGetNetwork(conn, def->name, def->uuid);
3414

3415
 cleanup:
3416
    virNetworkDefFree(newDef);
3417
    testObjectEventQueue(privconn, event);
3418 3419
    virNetworkObjEndAPI(&obj);
    return net;
3420 3421
}

3422 3423 3424 3425

static virNetworkPtr
testNetworkDefineXML(virConnectPtr conn,
                     const char *xml)
3426
{
3427
    testDriverPtr privconn = conn->privateData;
3428
    virNetworkDefPtr newDef;
3429
    virNetworkObjPtr obj = NULL;
3430
    virNetworkDefPtr def;
3431
    virNetworkPtr net = NULL;
3432
    virObjectEventPtr event = NULL;
3433

3434
    if ((newDef = virNetworkDefParseString(xml)) == NULL)
3435
        goto cleanup;
3436

3437
    if (!(obj = virNetworkObjAssignDef(privconn->networks, newDef, 0)))
3438
        goto cleanup;
3439 3440
    newDef = NULL;
    def = virNetworkObjGetDef(obj);
3441

3442
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
3443 3444
                                        VIR_NETWORK_EVENT_DEFINED,
                                        0);
3445

3446
    net = virGetNetwork(conn, def->name, def->uuid);
3447

3448
 cleanup:
3449
    virNetworkDefFree(newDef);
3450
    testObjectEventQueue(privconn, event);
3451 3452
    virNetworkObjEndAPI(&obj);
    return net;
3453 3454
}

3455 3456

static int
3457
testNetworkUndefine(virNetworkPtr net)
3458
{
3459 3460
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3461
    int ret = -1;
3462
    virObjectEventPtr event = NULL;
3463

3464
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3465
        goto cleanup;
3466

3467
    if (virNetworkObjIsActive(obj)) {
3468
        virReportError(VIR_ERR_OPERATION_INVALID,
3469
                       _("Network '%s' is still running"), net->name);
3470
        goto cleanup;
3471 3472
    }

3473
    event = virNetworkEventLifecycleNew(net->name, net->uuid,
3474 3475
                                        VIR_NETWORK_EVENT_UNDEFINED,
                                        0);
3476

3477
    virNetworkObjRemoveInactive(privconn->networks, obj);
3478
    ret = 0;
3479

3480
 cleanup:
3481
    testObjectEventQueue(privconn, event);
3482
    virNetworkObjEndAPI(&obj);
3483
    return ret;
3484 3485
}

3486

3487 3488 3489 3490 3491 3492 3493 3494
static int
testNetworkUpdate(virNetworkPtr net,
                  unsigned int command,
                  unsigned int section,
                  int parentIndex,
                  const char *xml,
                  unsigned int flags)
{
3495
    testDriverPtr privconn = net->conn->privateData;
3496
    virNetworkObjPtr obj = NULL;
3497 3498 3499 3500 3501 3502
    int isActive, ret = -1;

    virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
                  VIR_NETWORK_UPDATE_AFFECT_CONFIG,
                  -1);

3503
    if (!(obj = testNetworkObjFindByUUID(privconn, net->uuid)))
3504 3505 3506 3507 3508
        goto cleanup;

    /* VIR_NETWORK_UPDATE_AFFECT_CURRENT means "change LIVE if network
     * is active, else change CONFIG
    */
3509
    isActive = virNetworkObjIsActive(obj);
3510 3511 3512 3513 3514 3515 3516 3517 3518 3519
    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 */
3520
    if (virNetworkObjUpdate(obj, command, section, parentIndex, xml, flags) < 0)
3521 3522 3523
       goto cleanup;

    ret = 0;
3524
 cleanup:
3525
    virNetworkObjEndAPI(&obj);
3526 3527 3528
    return ret;
}

3529 3530

static int
3531
testNetworkCreate(virNetworkPtr net)
3532
{
3533 3534
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3535
    virNetworkDefPtr def;
3536
    int ret = -1;
3537
    virObjectEventPtr event = NULL;
3538

3539
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3540
        goto cleanup;
3541
    def = virNetworkObjGetDef(obj);
3542

3543
    if (virNetworkObjIsActive(obj)) {
3544
        virReportError(VIR_ERR_OPERATION_INVALID,
3545
                       _("Network '%s' is already running"), net->name);
3546
        goto cleanup;
3547 3548
    }

3549
    virNetworkObjSetActive(obj, true);
3550
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
3551 3552
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3553
    ret = 0;
3554

3555
 cleanup:
3556
    testObjectEventQueue(privconn, event);
3557
    virNetworkObjEndAPI(&obj);
3558
    return ret;
3559 3560
}

3561 3562

static int
3563
testNetworkDestroy(virNetworkPtr net)
3564
{
3565 3566
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3567
    virNetworkDefPtr def;
3568
    int ret = -1;
3569
    virObjectEventPtr event = NULL;
3570

3571
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3572
        goto cleanup;
3573
    def = virNetworkObjGetDef(obj);
3574

3575
    virNetworkObjSetActive(obj, false);
3576
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
3577 3578
                                        VIR_NETWORK_EVENT_STOPPED,
                                        0);
3579
    if (!virNetworkObjIsPersistent(obj))
3580
        virNetworkObjRemoveInactive(privconn->networks, obj);
3581

3582 3583
    ret = 0;

3584
 cleanup:
3585
    testObjectEventQueue(privconn, event);
3586
    virNetworkObjEndAPI(&obj);
3587
    return ret;
3588 3589
}

3590 3591

static char *
3592
testNetworkGetXMLDesc(virNetworkPtr net,
3593
                      unsigned int flags)
3594
{
3595 3596
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3597
    char *ret = NULL;
3598

E
Eric Blake 已提交
3599 3600
    virCheckFlags(0, NULL);

3601
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3602
        goto cleanup;
3603

3604
    ret = virNetworkDefFormat(virNetworkObjGetDef(obj), flags);
3605

3606
 cleanup:
3607
    virNetworkObjEndAPI(&obj);
3608
    return ret;
3609 3610
}

3611 3612

static char *
3613
testNetworkGetBridgeName(virNetworkPtr net)
3614
{
3615
    testDriverPtr privconn = net->conn->privateData;
3616
    char *bridge = NULL;
3617
    virNetworkObjPtr obj;
3618
    virNetworkDefPtr def;
3619

3620
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3621
        goto cleanup;
3622
    def = virNetworkObjGetDef(obj);
3623

3624
    if (!(def->bridge)) {
3625 3626
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("network '%s' does not have a bridge name."),
3627
                       def->name);
3628 3629 3630
        goto cleanup;
    }

3631
    ignore_value(VIR_STRDUP(bridge, def->bridge));
3632

3633
 cleanup:
3634
    virNetworkObjEndAPI(&obj);
3635 3636 3637
    return bridge;
}

3638 3639

static int
3640
testNetworkGetAutostart(virNetworkPtr net,
3641
                        int *autostart)
3642
{
3643 3644
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3645
    int ret = -1;
3646

3647
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3648
        goto cleanup;
3649

3650
    *autostart = virNetworkObjIsAutostart(obj) ? 1 : 0;
3651 3652
    ret = 0;

3653
 cleanup:
3654
    virNetworkObjEndAPI(&obj);
3655
    return ret;
3656 3657
}

3658 3659

static int
3660
testNetworkSetAutostart(virNetworkPtr net,
3661
                        int autostart)
3662
{
3663 3664
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3665
    bool new_autostart = (autostart != 0);
3666
    int ret = -1;
3667

3668
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3669
        goto cleanup;
3670

3671 3672
    virNetworkObjSetAutostart(obj, new_autostart);

3673 3674
    ret = 0;

3675
 cleanup:
3676
    virNetworkObjEndAPI(&obj);
3677
    return ret;
3678
}
3679

C
Cole Robinson 已提交
3680

L
Laine Stump 已提交
3681 3682 3683 3684 3685
/*
 * Physical host interface routines
 */


3686 3687 3688 3689
static virInterfaceObjPtr
testInterfaceObjFindByName(testDriverPtr privconn,
                           const char *name)
{
3690
    virInterfaceObjPtr obj;
3691 3692

    testDriverLock(privconn);
3693
    obj = virInterfaceObjListFindByName(privconn->ifaces, name);
3694 3695
    testDriverUnlock(privconn);

3696
    if (!obj)
3697 3698 3699 3700
        virReportError(VIR_ERR_NO_INTERFACE,
                       _("no interface with matching name '%s'"),
                       name);

3701
    return obj;
3702 3703 3704
}


3705 3706
static int
testConnectNumOfInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3707
{
3708
    testDriverPtr privconn = conn->privateData;
3709
    int ninterfaces;
L
Laine Stump 已提交
3710 3711

    testDriverLock(privconn);
3712
    ninterfaces = virInterfaceObjListNumOfInterfaces(privconn->ifaces, true);
L
Laine Stump 已提交
3713
    testDriverUnlock(privconn);
3714
    return ninterfaces;
L
Laine Stump 已提交
3715 3716
}

3717 3718 3719 3720 3721

static int
testConnectListInterfaces(virConnectPtr conn,
                          char **const names,
                          int maxnames)
L
Laine Stump 已提交
3722
{
3723
    testDriverPtr privconn = conn->privateData;
3724
    int nnames;
L
Laine Stump 已提交
3725 3726

    testDriverLock(privconn);
3727 3728
    nnames = virInterfaceObjListGetNames(privconn->ifaces, true,
                                         names, maxnames);
L
Laine Stump 已提交
3729 3730
    testDriverUnlock(privconn);

3731
    return nnames;
L
Laine Stump 已提交
3732 3733
}

3734 3735 3736

static int
testConnectNumOfDefinedInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3737
{
3738
    testDriverPtr privconn = conn->privateData;
3739
    int ninterfaces;
L
Laine Stump 已提交
3740 3741

    testDriverLock(privconn);
3742
    ninterfaces = virInterfaceObjListNumOfInterfaces(privconn->ifaces, false);
L
Laine Stump 已提交
3743
    testDriverUnlock(privconn);
3744
    return ninterfaces;
L
Laine Stump 已提交
3745 3746
}

3747 3748 3749 3750 3751

static int
testConnectListDefinedInterfaces(virConnectPtr conn,
                                 char **const names,
                                 int maxnames)
L
Laine Stump 已提交
3752
{
3753
    testDriverPtr privconn = conn->privateData;
3754
    int nnames;
L
Laine Stump 已提交
3755 3756

    testDriverLock(privconn);
3757 3758
    nnames = virInterfaceObjListGetNames(privconn->ifaces, false,
                                         names, maxnames);
L
Laine Stump 已提交
3759 3760
    testDriverUnlock(privconn);

3761
    return nnames;
L
Laine Stump 已提交
3762 3763
}

3764 3765 3766 3767

static virInterfacePtr
testInterfaceLookupByName(virConnectPtr conn,
                          const char *name)
L
Laine Stump 已提交
3768
{
3769
    testDriverPtr privconn = conn->privateData;
3770
    virInterfaceObjPtr obj;
3771
    virInterfaceDefPtr def;
L
Laine Stump 已提交
3772 3773
    virInterfacePtr ret = NULL;

3774
    if (!(obj = testInterfaceObjFindByName(privconn, name)))
3775
        return NULL;
3776
    def = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
3777

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

3780
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
3781 3782 3783
    return ret;
}

3784 3785 3786 3787

static virInterfacePtr
testInterfaceLookupByMACString(virConnectPtr conn,
                               const char *mac)
L
Laine Stump 已提交
3788
{
3789
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3790
    int ifacect;
3791
    char *ifacenames[] = { NULL, NULL };
L
Laine Stump 已提交
3792 3793 3794
    virInterfacePtr ret = NULL;

    testDriverLock(privconn);
3795 3796
    ifacect = virInterfaceObjListFindByMACString(privconn->ifaces, mac,
                                                 ifacenames, 2);
L
Laine Stump 已提交
3797 3798 3799
    testDriverUnlock(privconn);

    if (ifacect == 0) {
3800 3801
        virReportError(VIR_ERR_NO_INTERFACE,
                       _("no interface with matching mac '%s'"), mac);
L
Laine Stump 已提交
3802 3803 3804 3805
        goto cleanup;
    }

    if (ifacect > 1) {
3806
        virReportError(VIR_ERR_MULTIPLE_INTERFACES, NULL);
L
Laine Stump 已提交
3807 3808 3809
        goto cleanup;
    }

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

3812
 cleanup:
3813 3814
    VIR_FREE(ifacenames[0]);
    VIR_FREE(ifacenames[1]);
L
Laine Stump 已提交
3815 3816 3817
    return ret;
}

3818 3819 3820

static int
testInterfaceIsActive(virInterfacePtr iface)
3821
{
3822
    testDriverPtr privconn = iface->conn->privateData;
3823 3824 3825
    virInterfaceObjPtr obj;
    int ret = -1;

3826
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
3827
        return -1;
3828

3829 3830
    ret = virInterfaceObjIsActive(obj);

3831
    virInterfaceObjEndAPI(&obj);
3832 3833 3834
    return ret;
}

3835 3836 3837 3838

static int
testInterfaceChangeBegin(virConnectPtr conn,
                         unsigned int flags)
3839
{
3840
    testDriverPtr privconn = conn->privateData;
3841 3842
    int ret = -1;

E
Eric Blake 已提交
3843 3844
    virCheckFlags(0, -1);

3845 3846
    testDriverLock(privconn);
    if (privconn->transaction_running) {
3847
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3848
                       _("there is another transaction running."));
3849 3850 3851 3852 3853
        goto cleanup;
    }

    privconn->transaction_running = true;

3854
    if (!(privconn->backupIfaces = virInterfaceObjListClone(privconn->ifaces)))
3855 3856 3857
        goto cleanup;

    ret = 0;
3858
 cleanup:
3859 3860 3861 3862
    testDriverUnlock(privconn);
    return ret;
}

3863 3864 3865 3866

static int
testInterfaceChangeCommit(virConnectPtr conn,
                          unsigned int flags)
3867
{
3868
    testDriverPtr privconn = conn->privateData;
3869 3870
    int ret = -1;

E
Eric Blake 已提交
3871 3872
    virCheckFlags(0, -1);

3873 3874 3875
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3876
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3877 3878
                       _("no transaction running, "
                         "nothing to be committed."));
3879 3880 3881
        goto cleanup;
    }

3882
    virInterfaceObjListFree(privconn->backupIfaces);
3883 3884 3885 3886
    privconn->transaction_running = false;

    ret = 0;

3887
 cleanup:
3888 3889 3890 3891 3892
    testDriverUnlock(privconn);

    return ret;
}

3893 3894 3895 3896

static int
testInterfaceChangeRollback(virConnectPtr conn,
                            unsigned int flags)
3897
{
3898
    testDriverPtr privconn = conn->privateData;
3899 3900
    int ret = -1;

E
Eric Blake 已提交
3901 3902
    virCheckFlags(0, -1);

3903 3904 3905
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3906
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3907 3908
                       _("no transaction running, "
                         "nothing to rollback."));
3909 3910 3911
        goto cleanup;
    }

3912 3913 3914
    virInterfaceObjListFree(privconn->ifaces);
    privconn->ifaces = privconn->backupIfaces;
    privconn->backupIfaces = NULL;
3915 3916 3917 3918 3919

    privconn->transaction_running = false;

    ret = 0;

3920
 cleanup:
3921 3922 3923
    testDriverUnlock(privconn);
    return ret;
}
3924

3925 3926 3927 3928

static char *
testInterfaceGetXMLDesc(virInterfacePtr iface,
                        unsigned int flags)
L
Laine Stump 已提交
3929
{
3930
    testDriverPtr privconn = iface->conn->privateData;
3931
    virInterfaceObjPtr obj;
3932
    virInterfaceDefPtr def;
L
Laine Stump 已提交
3933 3934
    char *ret = NULL;

E
Eric Blake 已提交
3935 3936
    virCheckFlags(0, NULL);

3937
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
3938
        return NULL;
3939
    def = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
3940

3941
    ret = virInterfaceDefFormat(def);
L
Laine Stump 已提交
3942

3943
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
3944 3945 3946 3947
    return ret;
}


3948 3949 3950 3951
static virInterfacePtr
testInterfaceDefineXML(virConnectPtr conn,
                       const char *xmlStr,
                       unsigned int flags)
L
Laine Stump 已提交
3952
{
3953
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3954
    virInterfaceDefPtr def;
3955
    virInterfaceObjPtr obj = NULL;
3956
    virInterfaceDefPtr objdef;
L
Laine Stump 已提交
3957 3958
    virInterfacePtr ret = NULL;

E
Eric Blake 已提交
3959 3960
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
3961
    testDriverLock(privconn);
3962
    if ((def = virInterfaceDefParseString(xmlStr)) == NULL)
L
Laine Stump 已提交
3963 3964
        goto cleanup;

3965
    if ((obj = virInterfaceObjListAssignDef(privconn->ifaces, def)) == NULL)
L
Laine Stump 已提交
3966 3967
        goto cleanup;
    def = NULL;
3968
    objdef = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
3969

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

3972
 cleanup:
L
Laine Stump 已提交
3973
    virInterfaceDefFree(def);
3974
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
3975 3976 3977 3978
    testDriverUnlock(privconn);
    return ret;
}

3979 3980 3981

static int
testInterfaceUndefine(virInterfacePtr iface)
L
Laine Stump 已提交
3982
{
3983
    testDriverPtr privconn = iface->conn->privateData;
3984
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
3985

3986
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
3987
        return -1;
L
Laine Stump 已提交
3988

3989
    virInterfaceObjListRemove(privconn->ifaces, obj);
3990
    virObjectUnref(obj);
L
Laine Stump 已提交
3991

3992
    return 0;
L
Laine Stump 已提交
3993 3994
}

3995 3996 3997 3998

static int
testInterfaceCreate(virInterfacePtr iface,
                    unsigned int flags)
L
Laine Stump 已提交
3999
{
4000
    testDriverPtr privconn = iface->conn->privateData;
4001
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
4002 4003
    int ret = -1;

E
Eric Blake 已提交
4004 4005
    virCheckFlags(0, -1);

4006
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
4007
        return -1;
L
Laine Stump 已提交
4008

4009
    if (virInterfaceObjIsActive(obj)) {
4010
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
4011 4012 4013
        goto cleanup;
    }

4014
    virInterfaceObjSetActive(obj, true);
L
Laine Stump 已提交
4015 4016
    ret = 0;

4017
 cleanup:
4018
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
4019 4020 4021
    return ret;
}

4022 4023 4024 4025

static int
testInterfaceDestroy(virInterfacePtr iface,
                     unsigned int flags)
L
Laine Stump 已提交
4026
{
4027
    testDriverPtr privconn = iface->conn->privateData;
4028
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
4029 4030
    int ret = -1;

E
Eric Blake 已提交
4031 4032
    virCheckFlags(0, -1);

4033
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
4034
        return -1;
L
Laine Stump 已提交
4035

4036
    if (!virInterfaceObjIsActive(obj)) {
4037
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
4038 4039 4040
        goto cleanup;
    }

4041
    virInterfaceObjSetActive(obj, false);
L
Laine Stump 已提交
4042 4043
    ret = 0;

4044
 cleanup:
4045
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
4046 4047 4048 4049 4050
    return ret;
}



C
Cole Robinson 已提交
4051 4052 4053 4054
/*
 * Storage Driver routines
 */

4055
static int
4056
testStoragePoolObjSetDefaults(virStoragePoolObjPtr obj)
4057
{
C
Cole Robinson 已提交
4058

4059 4060 4061
    obj->def->capacity = defaultPoolCap;
    obj->def->allocation = defaultPoolAlloc;
    obj->def->available = defaultPoolCap - defaultPoolAlloc;
C
Cole Robinson 已提交
4062

4063
    return VIR_STRDUP(obj->configFile, "");
C
Cole Robinson 已提交
4064 4065
}

4066

4067 4068 4069 4070
static virStoragePoolObjPtr
testStoragePoolObjFindByName(testDriverPtr privconn,
                             const char *name)
{
4071
    virStoragePoolObjPtr obj;
4072 4073

    testDriverLock(privconn);
4074
    obj = virStoragePoolObjFindByName(&privconn->pools, name);
4075 4076
    testDriverUnlock(privconn);

4077
    if (!obj)
4078 4079 4080 4081
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       name);

4082
    return obj;
4083 4084 4085
}


4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125
static virStoragePoolObjPtr
testStoragePoolObjFindActiveByName(testDriverPtr privconn,
                                   const char *name)
{
    virStoragePoolObjPtr obj;

    if (!(obj = testStoragePoolObjFindByName(privconn, name)))
        return NULL;

    if (!virStoragePoolObjIsActive(obj)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), name);
        virStoragePoolObjUnlock(obj);
        return NULL;
    }

    return obj;
}


static virStoragePoolObjPtr
testStoragePoolObjFindInactiveByName(testDriverPtr privconn,
                                     const char *name)
{
    virStoragePoolObjPtr obj;

    if (!(obj = testStoragePoolObjFindByName(privconn, name)))
        return NULL;

    if (virStoragePoolObjIsActive(obj)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is active"), name);
        virStoragePoolObjUnlock(obj);
        return NULL;
    }

    return obj;
}


4126 4127 4128 4129
static virStoragePoolObjPtr
testStoragePoolObjFindByUUID(testDriverPtr privconn,
                             const unsigned char *uuid)
{
4130
    virStoragePoolObjPtr obj;
4131 4132 4133
    char uuidstr[VIR_UUID_STRING_BUFLEN];

    testDriverLock(privconn);
4134
    obj = virStoragePoolObjFindByUUID(&privconn->pools, uuid);
4135 4136
    testDriverUnlock(privconn);

4137
    if (!obj) {
4138 4139 4140 4141 4142 4143
        virUUIDFormat(uuid, uuidstr);
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching uuid '%s'"),
                       uuidstr);
    }

4144
    return obj;
4145 4146 4147
}


C
Cole Robinson 已提交
4148 4149
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
4150 4151
                            const unsigned char *uuid)
{
4152
    testDriverPtr privconn = conn->privateData;
4153 4154
    virStoragePoolObjPtr obj;
    virStoragePoolPtr pool = NULL;
C
Cole Robinson 已提交
4155

4156
    if (!(obj = testStoragePoolObjFindByUUID(privconn, uuid)))
4157
        return NULL;
C
Cole Robinson 已提交
4158

4159 4160
    pool = virGetStoragePool(conn, obj->def->name, obj->def->uuid,
                             NULL, NULL);
4161

4162
    virStoragePoolObjUnlock(obj);
4163
    return pool;
C
Cole Robinson 已提交
4164 4165
}

4166

C
Cole Robinson 已提交
4167 4168
static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
4169 4170
                            const char *name)
{
4171
    testDriverPtr privconn = conn->privateData;
4172 4173
    virStoragePoolObjPtr obj;
    virStoragePoolPtr pool = NULL;
C
Cole Robinson 已提交
4174

4175
    if (!(obj = testStoragePoolObjFindByName(privconn, name)))
4176
        return NULL;
C
Cole Robinson 已提交
4177

4178 4179
    pool = virGetStoragePool(conn, obj->def->name, obj->def->uuid,
                             NULL, NULL);
4180

4181
    virStoragePoolObjUnlock(obj);
4182
    return pool;
C
Cole Robinson 已提交
4183 4184
}

4185

C
Cole Robinson 已提交
4186
static virStoragePoolPtr
4187 4188
testStoragePoolLookupByVolume(virStorageVolPtr vol)
{
C
Cole Robinson 已提交
4189 4190 4191
    return testStoragePoolLookupByName(vol->conn, vol->pool);
}

4192

C
Cole Robinson 已提交
4193
static int
4194 4195
testConnectNumOfStoragePools(virConnectPtr conn)
{
4196
    testDriverPtr privconn = conn->privateData;
4197
    int numActive = 0;
C
Cole Robinson 已提交
4198

4199
    testDriverLock(privconn);
4200 4201
    numActive = virStoragePoolObjNumOfStoragePools(&privconn->pools, conn,
                                                   true, NULL);
4202
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4203 4204 4205 4206

    return numActive;
}

4207

C
Cole Robinson 已提交
4208
static int
4209 4210
testConnectListStoragePools(virConnectPtr conn,
                            char **const names,
4211
                            int maxnames)
4212
{
4213
    testDriverPtr privconn = conn->privateData;
4214
    int n = 0;
C
Cole Robinson 已提交
4215

4216
    testDriverLock(privconn);
4217 4218
    n = virStoragePoolObjGetNames(&privconn->pools, conn, true, NULL,
                                  names, maxnames);
4219
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4220 4221 4222 4223

    return n;
}

4224

C
Cole Robinson 已提交
4225
static int
4226 4227
testConnectNumOfDefinedStoragePools(virConnectPtr conn)
{
4228
    testDriverPtr privconn = conn->privateData;
4229
    int numInactive = 0;
C
Cole Robinson 已提交
4230

4231
    testDriverLock(privconn);
4232 4233
    numInactive = virStoragePoolObjNumOfStoragePools(&privconn->pools, conn,
                                                     false, NULL);
4234
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4235 4236 4237 4238

    return numInactive;
}

4239

C
Cole Robinson 已提交
4240
static int
4241 4242
testConnectListDefinedStoragePools(virConnectPtr conn,
                                   char **const names,
4243
                                   int maxnames)
4244
{
4245
    testDriverPtr privconn = conn->privateData;
4246
    int n = 0;
C
Cole Robinson 已提交
4247

4248
    testDriverLock(privconn);
4249 4250
    n = virStoragePoolObjGetNames(&privconn->pools, conn, false, NULL,
                                  names, maxnames);
4251
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4252 4253 4254 4255

    return n;
}

4256

4257
static int
4258 4259 4260
testConnectListAllStoragePools(virConnectPtr conn,
                               virStoragePoolPtr **pools,
                               unsigned int flags)
4261
{
4262
    testDriverPtr privconn = conn->privateData;
4263 4264 4265 4266 4267
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

    testDriverLock(privconn);
J
John Ferlan 已提交
4268
    ret = virStoragePoolObjListExport(conn, &privconn->pools, pools,
4269
                                      NULL, flags);
4270 4271 4272 4273
    testDriverUnlock(privconn);

    return ret;
}
C
Cole Robinson 已提交
4274

4275 4276 4277

static int
testStoragePoolIsActive(virStoragePoolPtr pool)
4278
{
4279
    testDriverPtr privconn = pool->conn->privateData;
4280 4281 4282
    virStoragePoolObjPtr obj;
    int ret = -1;

4283
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
4284
        goto cleanup;
4285

4286 4287
    ret = virStoragePoolObjIsActive(obj);

4288
 cleanup:
4289 4290 4291 4292 4293
    if (obj)
        virStoragePoolObjUnlock(obj);
    return ret;
}

4294 4295 4296

static int
testStoragePoolIsPersistent(virStoragePoolPtr pool)
4297
{
4298
    testDriverPtr privconn = pool->conn->privateData;
4299 4300 4301
    virStoragePoolObjPtr obj;
    int ret = -1;

4302
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
4303
        return -1;
4304

4305 4306
    ret = obj->configFile ? 1 : 0;

4307
    virStoragePoolObjUnlock(obj);
4308 4309 4310 4311
    return ret;
}


C
Cole Robinson 已提交
4312
static int
4313 4314
testStoragePoolCreate(virStoragePoolPtr pool,
                      unsigned int flags)
E
Eric Blake 已提交
4315
{
4316
    testDriverPtr privconn = pool->conn->privateData;
4317
    virStoragePoolObjPtr obj;
4318
    virObjectEventPtr event = NULL;
4319

E
Eric Blake 已提交
4320 4321
    virCheckFlags(0, -1);

4322 4323
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
4324

4325
    obj->active = 1;
4326 4327 4328 4329

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

4331
    testObjectEventQueue(privconn, event);
4332 4333
    virStoragePoolObjUnlock(obj);
    return 0;
C
Cole Robinson 已提交
4334 4335
}

4336

C
Cole Robinson 已提交
4337
static char *
4338 4339 4340 4341
testConnectFindStoragePoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type,
                                  const char *srcSpec,
                                  unsigned int flags)
C
Cole Robinson 已提交
4342
{
4343 4344 4345 4346
    virStoragePoolSourcePtr source = NULL;
    int pool_type;
    char *ret = NULL;

E
Eric Blake 已提交
4347 4348
    virCheckFlags(0, NULL);

4349 4350
    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
4351 4352
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
4353 4354 4355 4356
        goto cleanup;
    }

    if (srcSpec) {
4357
        source = virStoragePoolDefParseSourceString(srcSpec, pool_type);
4358 4359 4360 4361 4362 4363 4364
        if (!source)
            goto cleanup;
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
4365
        ignore_value(VIR_STRDUP(ret, defaultPoolSourcesLogicalXML));
4366 4367 4368
        break;

    case VIR_STORAGE_POOL_NETFS:
4369
        if (!source || !source->hosts[0].name) {
4370 4371
            virReportError(VIR_ERR_INVALID_ARG,
                           "%s", _("hostname must be specified for netfs sources"));
4372 4373 4374
            goto cleanup;
        }

4375 4376
        ignore_value(virAsprintf(&ret, defaultPoolSourcesNetFSXML,
                                 source->hosts[0].name));
4377 4378 4379
        break;

    default:
4380 4381
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source discovery"), type);
4382 4383
    }

4384
 cleanup:
4385 4386
    virStoragePoolSourceFree(source);
    return ret;
C
Cole Robinson 已提交
4387 4388 4389
}


4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411
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;
4412
    virNodeDeviceObjEndAPI(&obj);
4413 4414 4415 4416 4417

    return 0;
}


C
Cole Robinson 已提交
4418
static virStoragePoolPtr
4419 4420 4421
testStoragePoolCreateXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4422
{
4423
    testDriverPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4424
    virStoragePoolDefPtr def;
4425 4426
    virStoragePoolObjPtr obj = NULL;
    virStoragePoolPtr pool = NULL;
4427
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
4428

E
Eric Blake 已提交
4429 4430
    virCheckFlags(0, NULL);

4431
    testDriverLock(privconn);
4432
    if (!(def = virStoragePoolDefParseString(xml)))
4433
        goto cleanup;
C
Cole Robinson 已提交
4434

4435 4436 4437 4438
    obj = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid);
    if (!obj)
        obj = virStoragePoolObjFindByName(&privconn->pools, def->name);
    if (obj) {
4439 4440
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("storage pool already exists"));
4441
        goto cleanup;
C
Cole Robinson 已提交
4442 4443
    }

4444
    if (!(obj = virStoragePoolObjAssignDef(&privconn->pools, def)))
4445
        goto cleanup;
4446
    def = NULL;
C
Cole Robinson 已提交
4447

4448
    if (obj->def->source.adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
4449 4450 4451 4452 4453
        /* 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,
4454 4455 4456 4457
                            obj->def->source.adapter.data.fchost.wwnn,
                            obj->def->source.adapter.data.fchost.wwpn) < 0) {
            virStoragePoolObjRemove(&privconn->pools, obj);
            obj = NULL;
4458 4459 4460 4461
            goto cleanup;
        }
    }

4462 4463 4464
    if (testStoragePoolObjSetDefaults(obj) == -1) {
        virStoragePoolObjRemove(&privconn->pools, obj);
        obj = NULL;
4465
        goto cleanup;
C
Cole Robinson 已提交
4466
    }
4467 4468 4469 4470

    /* *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 */
4471
    VIR_FREE(obj->configFile);
4472

4473
    obj->active = 1;
C
Cole Robinson 已提交
4474

4475
    event = virStoragePoolEventLifecycleNew(obj->def->name, obj->def->uuid,
4476 4477 4478
                                            VIR_STORAGE_POOL_EVENT_STARTED,
                                            0);

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

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

4490

C
Cole Robinson 已提交
4491
static virStoragePoolPtr
4492 4493 4494
testStoragePoolDefineXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4495
{
4496
    testDriverPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4497
    virStoragePoolDefPtr def;
4498 4499
    virStoragePoolObjPtr obj = NULL;
    virStoragePoolPtr pool = NULL;
4500
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
4501

E
Eric Blake 已提交
4502 4503
    virCheckFlags(0, NULL);

4504
    testDriverLock(privconn);
4505
    if (!(def = virStoragePoolDefParseString(xml)))
4506
        goto cleanup;
C
Cole Robinson 已提交
4507 4508 4509 4510 4511

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

4512
    if (!(obj = virStoragePoolObjAssignDef(&privconn->pools, def)))
4513 4514
        goto cleanup;
    def = NULL;
C
Cole Robinson 已提交
4515

4516
    event = virStoragePoolEventLifecycleNew(obj->def->name, obj->def->uuid,
4517 4518 4519
                                            VIR_STORAGE_POOL_EVENT_DEFINED,
                                            0);

4520 4521 4522
    if (testStoragePoolObjSetDefaults(obj) == -1) {
        virStoragePoolObjRemove(&privconn->pools, obj);
        obj = NULL;
4523
        goto cleanup;
C
Cole Robinson 已提交
4524 4525
    }

4526
    pool = virGetStoragePool(conn, obj->def->name, obj->def->uuid, NULL, NULL);
4527

4528
 cleanup:
4529
    virStoragePoolDefFree(def);
4530
    testObjectEventQueue(privconn, event);
4531 4532
    if (obj)
        virStoragePoolObjUnlock(obj);
4533
    testDriverUnlock(privconn);
4534
    return pool;
C
Cole Robinson 已提交
4535 4536
}

4537

C
Cole Robinson 已提交
4538
static int
4539 4540
testStoragePoolUndefine(virStoragePoolPtr pool)
{
4541
    testDriverPtr privconn = pool->conn->privateData;
4542
    virStoragePoolObjPtr obj;
4543
    virObjectEventPtr event = NULL;
4544

4545 4546
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
4547

4548 4549 4550 4551
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_UNDEFINED,
                                            0);

4552
    virStoragePoolObjRemove(&privconn->pools, obj);
C
Cole Robinson 已提交
4553

4554
    testObjectEventQueue(privconn, event);
4555
    return 0;
C
Cole Robinson 已提交
4556 4557
}

4558

C
Cole Robinson 已提交
4559
static int
4560
testStoragePoolBuild(virStoragePoolPtr pool,
E
Eric Blake 已提交
4561 4562
                     unsigned int flags)
{
4563
    testDriverPtr privconn = pool->conn->privateData;
4564
    virStoragePoolObjPtr obj;
4565

E
Eric Blake 已提交
4566 4567
    virCheckFlags(0, -1);

4568 4569
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
4570

4571 4572
    virStoragePoolObjUnlock(obj);
    return 0;
C
Cole Robinson 已提交
4573 4574 4575
}


4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590
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 */
4591 4592
    if (!(obj = virNodeDeviceObjListFindByName(privconn->devs,
                                               "scsi_host12"))) {
4593 4594
        virReportError(VIR_ERR_NO_NODE_DEVICE, "%s",
                       _("no node device with matching name 'scsi_host12'"));
4595
        return -1;
4596 4597 4598 4599 4600 4601
    }

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

4602
    virNodeDeviceObjListRemove(privconn->devs, obj);
4603
    virObjectUnref(obj);
4604 4605

    testObjectEventQueue(privconn, event);
4606
    return 0;
4607 4608 4609
}


C
Cole Robinson 已提交
4610
static int
4611 4612
testStoragePoolDestroy(virStoragePoolPtr pool)
{
4613
    testDriverPtr privconn = pool->conn->privateData;
4614
    virStoragePoolObjPtr obj;
4615
    int ret = -1;
4616
    virObjectEventPtr event = NULL;
4617

4618
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
4619
        return -1;
4620

4621
    obj->active = 0;
4622

4623
    if (obj->def->source.adapter.type ==
4624
        VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
4625
        if (testDestroyVport(privconn,
4626 4627
                             obj->def->source.adapter.data.fchost.wwnn,
                             obj->def->source.adapter.data.fchost.wwpn) < 0)
4628 4629 4630
            goto cleanup;
    }

4631 4632
    event = virStoragePoolEventLifecycleNew(obj->def->name,
                                            obj->def->uuid,
4633 4634
                                            VIR_STORAGE_POOL_EVENT_STOPPED,
                                            0);
C
Cole Robinson 已提交
4635

4636 4637 4638
    if (obj->configFile == NULL) {
        virStoragePoolObjRemove(&privconn->pools, obj);
        obj = NULL;
4639
    }
4640
    ret = 0;
C
Cole Robinson 已提交
4641

4642
 cleanup:
4643
    testObjectEventQueue(privconn, event);
4644 4645
    if (obj)
        virStoragePoolObjUnlock(obj);
4646
    return ret;
C
Cole Robinson 已提交
4647 4648 4649 4650
}


static int
4651
testStoragePoolDelete(virStoragePoolPtr pool,
E
Eric Blake 已提交
4652 4653
                      unsigned int flags)
{
4654
    testDriverPtr privconn = pool->conn->privateData;
4655
    virStoragePoolObjPtr obj;
4656

E
Eric Blake 已提交
4657 4658
    virCheckFlags(0, -1);

4659 4660
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
4661

4662 4663
    virStoragePoolObjUnlock(obj);
    return 0;
C
Cole Robinson 已提交
4664 4665 4666 4667
}


static int
4668
testStoragePoolRefresh(virStoragePoolPtr pool,
E
Eric Blake 已提交
4669 4670
                       unsigned int flags)
{
4671
    testDriverPtr privconn = pool->conn->privateData;
4672
    virStoragePoolObjPtr obj;
4673
    virObjectEventPtr event = NULL;
4674

E
Eric Blake 已提交
4675 4676
    virCheckFlags(0, -1);

4677 4678
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return -1;
4679

4680
    event = virStoragePoolEventRefreshNew(pool->name, pool->uuid);
C
Cole Robinson 已提交
4681

4682
    testObjectEventQueue(privconn, event);
4683 4684
    virStoragePoolObjUnlock(obj);
    return 0;
C
Cole Robinson 已提交
4685 4686 4687 4688
}


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

4695
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
4696
        return -1;
C
Cole Robinson 已提交
4697 4698

    memset(info, 0, sizeof(virStoragePoolInfo));
4699
    if (obj->active)
C
Cole Robinson 已提交
4700 4701 4702
        info->state = VIR_STORAGE_POOL_RUNNING;
    else
        info->state = VIR_STORAGE_POOL_INACTIVE;
4703 4704 4705
    info->capacity = obj->def->capacity;
    info->allocation = obj->def->allocation;
    info->available = obj->def->available;
C
Cole Robinson 已提交
4706

4707 4708
    virStoragePoolObjUnlock(obj);
    return 0;
C
Cole Robinson 已提交
4709 4710
}

4711

C
Cole Robinson 已提交
4712
static char *
4713
testStoragePoolGetXMLDesc(virStoragePoolPtr pool,
E
Eric Blake 已提交
4714 4715
                          unsigned int flags)
{
4716
    testDriverPtr privconn = pool->conn->privateData;
4717
    virStoragePoolObjPtr obj;
4718
    char *ret = NULL;
4719

E
Eric Blake 已提交
4720 4721
    virCheckFlags(0, NULL);

4722
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
4723
        return NULL;
4724

4725
    ret = virStoragePoolDefFormat(obj->def);
4726

4727
    virStoragePoolObjUnlock(obj);
4728
    return ret;
C
Cole Robinson 已提交
4729 4730
}

4731

C
Cole Robinson 已提交
4732
static int
4733
testStoragePoolGetAutostart(virStoragePoolPtr pool,
4734 4735
                            int *autostart)
{
4736
    testDriverPtr privconn = pool->conn->privateData;
4737
    virStoragePoolObjPtr obj;
4738

4739
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
4740
        return -1;
C
Cole Robinson 已提交
4741

4742
    if (!obj->configFile) {
C
Cole Robinson 已提交
4743 4744
        *autostart = 0;
    } else {
4745
        *autostart = obj->autostart;
C
Cole Robinson 已提交
4746 4747
    }

4748 4749
    virStoragePoolObjUnlock(obj);
    return 0;
C
Cole Robinson 已提交
4750 4751
}

4752

C
Cole Robinson 已提交
4753
static int
4754
testStoragePoolSetAutostart(virStoragePoolPtr pool,
4755 4756
                            int autostart)
{
4757
    testDriverPtr privconn = pool->conn->privateData;
4758
    virStoragePoolObjPtr obj;
4759
    int ret = -1;
4760

4761
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
4762
        return -1;
C
Cole Robinson 已提交
4763

4764
    if (!obj->configFile) {
4765 4766
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("pool has no config file"));
4767
        goto cleanup;
C
Cole Robinson 已提交
4768 4769 4770
    }

    autostart = (autostart != 0);
4771
    obj->autostart = autostart;
4772 4773
    ret = 0;

4774
 cleanup:
4775
    virStoragePoolObjUnlock(obj);
4776
    return ret;
C
Cole Robinson 已提交
4777 4778 4779 4780
}


static int
4781 4782
testStoragePoolNumOfVolumes(virStoragePoolPtr pool)
{
4783
    testDriverPtr privconn = pool->conn->privateData;
4784
    virStoragePoolObjPtr obj;
4785
    int ret = -1;
4786

4787 4788
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
4789

4790
    ret = virStoragePoolObjNumOfVolumes(obj, pool->conn, NULL);
4791

4792
    virStoragePoolObjUnlock(obj);
4793
    return ret;
C
Cole Robinson 已提交
4794 4795
}

4796

C
Cole Robinson 已提交
4797
static int
4798
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4799
                           char **const names,
4800 4801
                           int maxnames)
{
4802
    testDriverPtr privconn = pool->conn->privateData;
4803
    virStoragePoolObjPtr obj;
4804
    int n = -1;
4805

4806
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
4807
        return -1;
4808

4809
    n = virStoragePoolObjVolumeGetNames(obj, pool->conn, NULL, names, maxnames);
C
Cole Robinson 已提交
4810

4811
    virStoragePoolObjUnlock(obj);
C
Cole Robinson 已提交
4812 4813 4814
    return n;
}

4815

4816
static int
4817
testStoragePoolListAllVolumes(virStoragePoolPtr pool,
4818
                              virStorageVolPtr **vols,
4819 4820
                              unsigned int flags)
{
4821 4822
    testDriverPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr obj;
4823 4824 4825 4826
    int ret = -1;

    virCheckFlags(0, -1);

4827
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
4828
        return -1;
4829

4830
    if (!virStoragePoolObjIsActive(obj)) {
4831 4832 4833 4834 4835
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("storage pool is not active"));
        goto cleanup;
    }

4836
    ret = virStoragePoolObjVolumeListExport(pool->conn, obj, vols, NULL);
4837 4838

 cleanup:
4839
    virStoragePoolObjUnlock(obj);
4840 4841 4842

    return ret;
}
C
Cole Robinson 已提交
4843

4844

4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859
static virStorageVolDefPtr
testStorageVolDefFindByName(virStoragePoolObjPtr obj,
                            const char *name)
{
    virStorageVolDefPtr privvol;

    if (!(privvol = virStorageVolDefFindByName(obj, name))) {
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"), name);
    }

    return privvol;
}


C
Cole Robinson 已提交
4860
static virStorageVolPtr
4861
testStorageVolLookupByName(virStoragePoolPtr pool,
4862
                           const char *name)
4863
{
4864
    testDriverPtr privconn = pool->conn->privateData;
4865
    virStoragePoolObjPtr obj;
4866
    virStorageVolDefPtr privvol;
4867
    virStorageVolPtr ret = NULL;
4868

4869 4870
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return NULL;
4871

4872
    if (!(privvol = testStorageVolDefFindByName(obj, name)))
4873
        goto cleanup;
C
Cole Robinson 已提交
4874

4875
    ret = virGetStorageVol(pool->conn, obj->def->name,
4876 4877
                           privvol->name, privvol->key,
                           NULL, NULL);
4878

4879
 cleanup:
4880
    virStoragePoolObjUnlock(obj);
4881
    return ret;
C
Cole Robinson 已提交
4882 4883 4884 4885
}


static virStorageVolPtr
4886
testStorageVolLookupByKey(virConnectPtr conn,
4887 4888
                          const char *key)
{
4889
    testDriverPtr privconn = conn->privateData;
4890
    size_t i;
4891
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4892

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

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

4914
    if (!ret)
4915 4916
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching key '%s'"), key);
4917 4918

    return ret;
C
Cole Robinson 已提交
4919 4920
}

4921

C
Cole Robinson 已提交
4922
static virStorageVolPtr
4923
testStorageVolLookupByPath(virConnectPtr conn,
4924 4925
                           const char *path)
{
4926
    testDriverPtr privconn = conn->privateData;
4927
    size_t i;
4928
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4929

4930
    testDriverLock(privconn);
4931
    for (i = 0; i < privconn->pools.count; i++) {
4932
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4933
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4934
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4935 4936
                virStorageVolDefFindByPath(privconn->pools.objs[i], path);

4937 4938 4939 4940
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
4941 4942
                                       privvol->key,
                                       NULL, NULL);
4943
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
4944 4945
                break;
            }
C
Cole Robinson 已提交
4946
        }
4947
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4948
    }
4949
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4950

4951
    if (!ret)
4952 4953
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching path '%s'"), path);
4954 4955

    return ret;
C
Cole Robinson 已提交
4956 4957
}

4958

C
Cole Robinson 已提交
4959
static virStorageVolPtr
4960 4961 4962
testStorageVolCreateXML(virStoragePoolPtr pool,
                        const char *xmldesc,
                        unsigned int flags)
E
Eric Blake 已提交
4963
{
4964
    testDriverPtr privconn = pool->conn->privateData;
4965
    virStoragePoolObjPtr obj;
4966 4967
    virStorageVolDefPtr privvol = NULL;
    virStorageVolPtr ret = NULL;
4968

E
Eric Blake 已提交
4969 4970
    virCheckFlags(0, NULL);

4971 4972
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return NULL;
C
Cole Robinson 已提交
4973

4974
    privvol = virStorageVolDefParseString(obj->def, xmldesc, 0);
4975
    if (privvol == NULL)
4976
        goto cleanup;
4977

4978
    if (virStorageVolDefFindByName(obj, privvol->name)) {
4979 4980
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
4981
        goto cleanup;
C
Cole Robinson 已提交
4982 4983 4984
    }

    /* Make sure enough space */
4985 4986
    if ((obj->def->allocation + privvol->target.allocation) >
         obj->def->capacity) {
4987 4988 4989
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
4990
        goto cleanup;
C
Cole Robinson 已提交
4991 4992
    }

4993
    if (virAsprintf(&privvol->target.path, "%s/%s",
4994
                    obj->def->target.path, privvol->name) < 0)
4995
        goto cleanup;
C
Cole Robinson 已提交
4996

4997
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
4998 4999
        VIR_APPEND_ELEMENT_COPY(obj->volumes.objs,
                                obj->volumes.count, privvol) < 0)
5000
        goto cleanup;
C
Cole Robinson 已提交
5001

5002 5003
    obj->def->allocation += privvol->target.allocation;
    obj->def->available = (obj->def->capacity - obj->def->allocation);
C
Cole Robinson 已提交
5004

5005
    ret = virGetStorageVol(pool->conn, obj->def->name,
5006 5007
                           privvol->name, privvol->key,
                           NULL, NULL);
5008
    privvol = NULL;
5009

5010
 cleanup:
5011
    virStorageVolDefFree(privvol);
5012
    virStoragePoolObjUnlock(obj);
5013
    return ret;
C
Cole Robinson 已提交
5014 5015
}

5016

5017
static virStorageVolPtr
5018 5019 5020 5021
testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
                            const char *xmldesc,
                            virStorageVolPtr clonevol,
                            unsigned int flags)
E
Eric Blake 已提交
5022
{
5023
    testDriverPtr privconn = pool->conn->privateData;
5024
    virStoragePoolObjPtr obj;
5025 5026 5027
    virStorageVolDefPtr privvol = NULL, origvol = NULL;
    virStorageVolPtr ret = NULL;

E
Eric Blake 已提交
5028 5029
    virCheckFlags(0, NULL);

5030 5031
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return NULL;
5032

5033
    privvol = virStorageVolDefParseString(obj->def, xmldesc, 0);
5034 5035 5036
    if (privvol == NULL)
        goto cleanup;

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

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

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

5061
    if (virAsprintf(&privvol->target.path, "%s/%s",
5062
                    obj->def->target.path, privvol->name) < 0)
5063 5064
        goto cleanup;

5065
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
5066 5067
        VIR_APPEND_ELEMENT_COPY(obj->volumes.objs,
                                obj->volumes.count, privvol) < 0)
5068 5069
        goto cleanup;

5070 5071
    obj->def->allocation += privvol->target.allocation;
    obj->def->available = (obj->def->capacity - obj->def->allocation);
5072

5073
    ret = virGetStorageVol(pool->conn, obj->def->name,
5074 5075
                           privvol->name, privvol->key,
                           NULL, NULL);
5076 5077
    privvol = NULL;

5078
 cleanup:
5079
    virStorageVolDefFree(privvol);
5080
    virStoragePoolObjUnlock(obj);
5081 5082 5083
    return ret;
}

5084

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

E
Eric Blake 已提交
5095 5096
    virCheckFlags(0, -1);

5097 5098
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return -1;
5099

5100
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
5101
        goto cleanup;
5102

5103 5104
    obj->def->allocation -= privvol->target.allocation;
    obj->def->available = (obj->def->capacity - obj->def->allocation);
C
Cole Robinson 已提交
5105

5106 5107
    for (i = 0; i < obj->volumes.count; i++) {
        if (obj->volumes.objs[i] == privvol) {
C
Cole Robinson 已提交
5108 5109
            virStorageVolDefFree(privvol);

5110
            VIR_DELETE_ELEMENT(obj->volumes.objs, i, obj->volumes.count);
C
Cole Robinson 已提交
5111 5112 5113
            break;
        }
    }
5114
    ret = 0;
C
Cole Robinson 已提交
5115

5116
 cleanup:
5117
    virStoragePoolObjUnlock(obj);
5118
    return ret;
C
Cole Robinson 已提交
5119 5120 5121
}


5122 5123
static int
testStorageVolumeTypeForPool(int pooltype)
5124
{
C
Cole Robinson 已提交
5125

5126
    switch (pooltype) {
C
Cole Robinson 已提交
5127 5128 5129 5130 5131 5132 5133 5134 5135
        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;
    }
}

5136

C
Cole Robinson 已提交
5137
static int
5138
testStorageVolGetInfo(virStorageVolPtr vol,
5139 5140
                      virStorageVolInfoPtr info)
{
5141
    testDriverPtr privconn = vol->conn->privateData;
5142
    virStoragePoolObjPtr obj;
5143
    virStorageVolDefPtr privvol;
5144
    int ret = -1;
5145

5146 5147
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return -1;
5148

5149
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
5150
        goto cleanup;
5151

C
Cole Robinson 已提交
5152
    memset(info, 0, sizeof(*info));
5153
    info->type = testStorageVolumeTypeForPool(obj->def->type);
5154 5155
    info->capacity = privvol->target.capacity;
    info->allocation = privvol->target.allocation;
5156
    ret = 0;
C
Cole Robinson 已提交
5157

5158
 cleanup:
5159
    virStoragePoolObjUnlock(obj);
5160
    return ret;
C
Cole Robinson 已提交
5161 5162
}

5163

C
Cole Robinson 已提交
5164
static char *
5165 5166
testStorageVolGetXMLDesc(virStorageVolPtr vol,
                         unsigned int flags)
E
Eric Blake 已提交
5167
{
5168
    testDriverPtr privconn = vol->conn->privateData;
5169
    virStoragePoolObjPtr obj;
5170
    virStorageVolDefPtr privvol;
5171
    char *ret = NULL;
5172

E
Eric Blake 已提交
5173 5174
    virCheckFlags(0, NULL);

5175 5176
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return NULL;
5177

5178
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
5179
        goto cleanup;
C
Cole Robinson 已提交
5180

5181
    ret = virStorageVolDefFormat(obj->def, privvol);
5182

5183
 cleanup:
5184
    virStoragePoolObjUnlock(obj);
5185
    return ret;
C
Cole Robinson 已提交
5186 5187
}

5188

C
Cole Robinson 已提交
5189
static char *
5190 5191
testStorageVolGetPath(virStorageVolPtr vol)
{
5192
    testDriverPtr privconn = vol->conn->privateData;
5193
    virStoragePoolObjPtr obj;
5194
    virStorageVolDefPtr privvol;
5195
    char *ret = NULL;
5196

5197 5198
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return NULL;
5199

5200
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
5201
        goto cleanup;
5202

5203
    ignore_value(VIR_STRDUP(ret, privvol->target.path));
5204

5205
 cleanup:
5206
    virStoragePoolObjUnlock(obj);
C
Cole Robinson 已提交
5207 5208 5209
    return ret;
}

5210

5211
/* Node device implementations */
5212

5213 5214 5215 5216 5217 5218
static virNodeDeviceObjPtr
testNodeDeviceObjFindByName(testDriverPtr driver,
                            const char *name)
{
    virNodeDeviceObjPtr obj;

5219
    if (!(obj = virNodeDeviceObjListFindByName(driver->devs, name)))
5220 5221 5222 5223 5224 5225 5226 5227
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       name);

    return obj;
}


5228 5229 5230
static int
testNodeNumOfDevices(virConnectPtr conn,
                     const char *cap,
E
Eric Blake 已提交
5231
                     unsigned int flags)
5232
{
5233
    testDriverPtr driver = conn->privateData;
5234

E
Eric Blake 已提交
5235 5236
    virCheckFlags(0, -1);

5237
    return virNodeDeviceObjListNumOfDevices(driver->devs, conn, cap, NULL);
5238 5239
}

5240

5241 5242 5243 5244 5245
static int
testNodeListDevices(virConnectPtr conn,
                    const char *cap,
                    char **const names,
                    int maxnames,
E
Eric Blake 已提交
5246
                    unsigned int flags)
5247
{
5248
    testDriverPtr driver = conn->privateData;
5249

E
Eric Blake 已提交
5250 5251
    virCheckFlags(0, -1);

5252 5253
    return virNodeDeviceObjListGetNames(driver->devs, conn, NULL,
                                        cap, names, maxnames);
5254 5255
}

5256

5257 5258 5259
static virNodeDevicePtr
testNodeDeviceLookupByName(virConnectPtr conn, const char *name)
{
5260
    testDriverPtr driver = conn->privateData;
5261
    virNodeDeviceObjPtr obj;
5262
    virNodeDeviceDefPtr def;
5263 5264
    virNodeDevicePtr ret = NULL;

5265
    if (!(obj = testNodeDeviceObjFindByName(driver, name)))
5266
        return NULL;
5267
    def = virNodeDeviceObjGetDef(obj);
5268

5269
    if ((ret = virGetNodeDevice(conn, name))) {
5270
        if (VIR_STRDUP(ret->parent, def->parent) < 0) {
5271
            virObjectUnref(ret);
5272 5273
            ret = NULL;
        }
5274
    }
5275

5276
    virNodeDeviceObjEndAPI(&obj);
5277 5278 5279 5280
    return ret;
}

static char *
5281
testNodeDeviceGetXMLDesc(virNodeDevicePtr dev,
E
Eric Blake 已提交
5282
                         unsigned int flags)
5283
{
5284
    testDriverPtr driver = dev->conn->privateData;
5285 5286 5287
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

E
Eric Blake 已提交
5288 5289
    virCheckFlags(0, NULL);

5290
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5291
        return NULL;
5292

5293
    ret = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(obj));
5294

5295
    virNodeDeviceObjEndAPI(&obj);
5296 5297 5298 5299 5300 5301
    return ret;
}

static char *
testNodeDeviceGetParent(virNodeDevicePtr dev)
{
5302
    testDriverPtr driver = dev->conn->privateData;
5303
    virNodeDeviceObjPtr obj;
5304
    virNodeDeviceDefPtr def;
5305 5306
    char *ret = NULL;

5307
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5308
        return NULL;
5309
    def = virNodeDeviceObjGetDef(obj);
5310

5311 5312
    if (def->parent) {
        ignore_value(VIR_STRDUP(ret, def->parent));
5313
    } else {
5314 5315
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no parent for this device"));
5316 5317
    }

5318
    virNodeDeviceObjEndAPI(&obj);
5319 5320 5321
    return ret;
}

5322

5323 5324 5325
static int
testNodeDeviceNumOfCaps(virNodeDevicePtr dev)
{
5326
    testDriverPtr driver = dev->conn->privateData;
5327
    virNodeDeviceObjPtr obj;
5328
    virNodeDeviceDefPtr def;
5329 5330 5331
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;

5332
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5333
        return -1;
5334
    def = virNodeDeviceObjGetDef(obj);
5335

5336
    for (caps = def->caps; caps; caps = caps->next)
5337 5338
        ++ncaps;

5339
    virNodeDeviceObjEndAPI(&obj);
5340
    return ncaps;
5341 5342 5343 5344 5345 5346
}


static int
testNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
5347
    testDriverPtr driver = dev->conn->privateData;
5348
    virNodeDeviceObjPtr obj;
5349
    virNodeDeviceDefPtr def;
5350 5351 5352
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;

5353
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5354
        return -1;
5355
    def = virNodeDeviceObjGetDef(obj);
5356

5357
    for (caps = def->caps; caps && ncaps < maxnames; caps = caps->next) {
5358 5359 5360 5361
        if (VIR_STRDUP(names[ncaps],
                       virNodeDevCapTypeToString(caps->data.type)) < 0)
            goto error;
        ncaps++;
5362 5363
    }

5364
    virNodeDeviceObjEndAPI(&obj);
5365 5366 5367 5368 5369
    return ncaps;

 error:
    while (--ncaps >= 0)
        VIR_FREE(names[ncaps]);
5370
    virNodeDeviceObjEndAPI(&obj);
5371
    return -1;
5372 5373
}

5374

5375 5376
static virNodeDeviceObjPtr
testNodeDeviceMockCreateVport(testDriverPtr driver,
5377
                              const char *wwnn,
5378
                              const char *wwpn)
5379
{
5380 5381
    char *xml = NULL;
    virNodeDeviceDefPtr def = NULL;
5382
    virNodeDevCapsDefPtr caps;
5383
    virNodeDeviceObjPtr obj = NULL, objcopy = NULL;
5384
    virNodeDeviceDefPtr objdef;
5385
    virObjectEventPtr event = NULL;
5386

5387 5388 5389 5390 5391 5392 5393 5394 5395
    /* 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. */
5396 5397
    if (!(objcopy = virNodeDeviceObjListFindByName(driver->devs,
                                                   "scsi_host11")))
5398 5399
        goto cleanup;

5400
    xml = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(objcopy));
5401
    virNodeDeviceObjEndAPI(&objcopy);
5402 5403 5404 5405
    if (!xml)
        goto cleanup;

    if (!(def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL)))
5406 5407
        goto cleanup;

5408
    VIR_FREE(def->name);
5409
    if (VIR_STRDUP(def->name, "scsi_host12") < 0)
5410 5411
        goto cleanup;

5412 5413 5414
    /* 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. */
5415 5416
    caps = def->caps;
    while (caps) {
5417
        if (caps->data.type != VIR_NODE_DEV_CAP_SCSI_HOST)
5418 5419
            continue;

5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433
        /* 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++;
        }
5434 5435 5436
        caps = caps->next;
    }

5437
    if (!(obj = virNodeDeviceObjListAssignDef(driver->devs, def)))
5438
        goto cleanup;
5439
    def = NULL;
5440
    objdef = virNodeDeviceObjGetDef(obj);
5441

5442
    event = virNodeDeviceEventLifecycleNew(objdef->name,
5443 5444
                                           VIR_NODE_DEVICE_EVENT_CREATED,
                                           0);
5445 5446 5447
    testObjectEventQueue(driver, event);

 cleanup:
5448
    VIR_FREE(xml);
5449 5450
    virNodeDeviceDefFree(def);
    return obj;
5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461
}


static virNodeDevicePtr
testNodeDeviceCreateXML(virConnectPtr conn,
                        const char *xmlDesc,
                        unsigned int flags)
{
    testDriverPtr driver = conn->privateData;
    virNodeDeviceDefPtr def = NULL;
    char *wwnn = NULL, *wwpn = NULL;
5462 5463
    virNodeDevicePtr dev = NULL, ret = NULL;
    virNodeDeviceObjPtr obj = NULL;
5464
    virNodeDeviceDefPtr objdef;
5465 5466 5467 5468 5469 5470

    virCheckFlags(0, NULL);

    if (!(def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, NULL)))
        goto cleanup;

5471 5472 5473
    /* We run this simply for validation - it essentially validates that
     * the input XML either has a wwnn/wwpn or virNodeDevCapSCSIHostParseXML
     * generated a wwnn/wwpn */
5474 5475 5476
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) < 0)
        goto cleanup;

5477 5478 5479
    /* 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. */
5480
    if (virNodeDeviceObjListGetParentHost(driver->devs, def) < 0)
5481 5482 5483 5484
        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
5485 5486 5487
     * 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 */
5488 5489
    if (!(obj = testNodeDeviceMockCreateVport(driver, wwnn, wwpn)))
        goto cleanup;
5490
    objdef = virNodeDeviceObjGetDef(obj);
5491

5492
    if (!(dev = virGetNodeDevice(conn, objdef->name)))
5493 5494 5495 5496 5497 5498 5499 5500
        goto cleanup;

    VIR_FREE(dev->parent);
    if (VIR_STRDUP(dev->parent, def->parent) < 0)
        goto cleanup;

    ret = dev;
    dev = NULL;
5501

5502
 cleanup:
5503
    virNodeDeviceObjEndAPI(&obj);
5504
    virNodeDeviceDefFree(def);
5505
    virObjectUnref(dev);
5506 5507
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
5508
    return ret;
5509 5510 5511 5512 5513 5514
}

static int
testNodeDeviceDestroy(virNodeDevicePtr dev)
{
    int ret = 0;
5515
    testDriverPtr driver = dev->conn->privateData;
5516
    virNodeDeviceObjPtr obj = NULL;
5517
    virNodeDeviceObjPtr parentobj = NULL;
5518
    virNodeDeviceDefPtr def;
5519
    char *wwnn = NULL, *wwpn = NULL;
5520
    virObjectEventPtr event = NULL;
5521

5522
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5523
        return -1;
5524
    def = virNodeDeviceObjGetDef(obj);
5525

5526
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) == -1)
5527
        goto cleanup;
5528

5529 5530 5531 5532
    /* Unlike the real code we cannot run into the udevAddOneDevice race
     * which would replace obj->def, so no need to save off the parent,
     * but do need to drop the @obj lock so that the FindByName code doesn't
     * deadlock on ourselves */
5533
    virObjectUnlock(obj);
5534

5535 5536 5537 5538 5539 5540
    /* We do this just for basic validation and throw away the parentobj
     * since there's no vport_delete to be run */
    if (!(parentobj = virNodeDeviceObjListFindByName(driver->devs,
                                                     def->parent))) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("cannot find parent '%s' definition"), def->parent);
5541
        virObjectLock(obj);
5542
        goto cleanup;
5543
    }
5544
    virNodeDeviceObjEndAPI(&parentobj);
5545

5546 5547 5548 5549
    event = virNodeDeviceEventLifecycleNew(dev->name,
                                           VIR_NODE_DEVICE_EVENT_DELETED,
                                           0);

5550
    virObjectLock(obj);
5551
    virNodeDeviceObjListRemove(driver->devs, obj);
5552
    virObjectUnref(obj);
5553
    obj = NULL;
5554

5555
 cleanup:
5556
    virNodeDeviceObjEndAPI(&obj);
5557
    testObjectEventQueue(driver, event);
5558 5559 5560 5561 5562
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return ret;
}

5563 5564

/* Domain event implementations */
5565
static int
5566 5567 5568 5569
testConnectDomainEventRegister(virConnectPtr conn,
                               virConnectDomainEventCallback callback,
                               void *opaque,
                               virFreeCallback freecb)
5570
{
5571
    testDriverPtr driver = conn->privateData;
5572
    int ret = 0;
5573

5574
    if (virDomainEventStateRegister(conn, driver->eventState,
5575 5576
                                    callback, opaque, freecb) < 0)
        ret = -1;
5577 5578 5579 5580

    return ret;
}

5581

5582
static int
5583 5584
testConnectDomainEventDeregister(virConnectPtr conn,
                                 virConnectDomainEventCallback callback)
5585
{
5586
    testDriverPtr driver = conn->privateData;
5587
    int ret = 0;
5588

5589
    if (virDomainEventStateDeregister(conn, driver->eventState,
5590 5591
                                      callback) < 0)
        ret = -1;
5592 5593 5594 5595

    return ret;
}

5596 5597

static int
5598 5599 5600 5601 5602 5603
testConnectDomainEventRegisterAny(virConnectPtr conn,
                                  virDomainPtr dom,
                                  int eventID,
                                  virConnectDomainEventGenericCallback callback,
                                  void *opaque,
                                  virFreeCallback freecb)
5604
{
5605
    testDriverPtr driver = conn->privateData;
5606 5607
    int ret;

5608
    if (virDomainEventStateRegisterID(conn, driver->eventState,
5609 5610
                                      dom, eventID,
                                      callback, opaque, freecb, &ret) < 0)
5611
        ret = -1;
5612 5613 5614 5615 5616

    return ret;
}

static int
5617 5618
testConnectDomainEventDeregisterAny(virConnectPtr conn,
                                    int callbackID)
5619
{
5620
    testDriverPtr driver = conn->privateData;
5621
    int ret = 0;
5622

5623
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5624
                                        callbackID, true) < 0)
5625
        ret = -1;
5626 5627 5628 5629 5630

    return ret;
}


5631 5632 5633 5634 5635 5636 5637 5638
static int
testConnectNetworkEventRegisterAny(virConnectPtr conn,
                                   virNetworkPtr net,
                                   int eventID,
                                   virConnectNetworkEventGenericCallback callback,
                                   void *opaque,
                                   virFreeCallback freecb)
{
5639
    testDriverPtr driver = conn->privateData;
5640 5641
    int ret;

5642
    if (virNetworkEventStateRegisterID(conn, driver->eventState,
5643
                                       net, eventID, callback,
5644 5645 5646 5647 5648 5649 5650 5651 5652 5653
                                       opaque, freecb, &ret) < 0)
        ret = -1;

    return ret;
}

static int
testConnectNetworkEventDeregisterAny(virConnectPtr conn,
                                     int callbackID)
{
5654
    testDriverPtr driver = conn->privateData;
5655
    int ret = 0;
5656

5657
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5658
                                        callbackID, true) < 0)
5659
        ret = -1;
5660 5661 5662 5663

    return ret;
}

5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690
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,
5691
                                        callbackID, true) < 0)
5692 5693 5694 5695 5696
        ret = -1;

    return ret;
}

5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723
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,
5724
                                        callbackID, true) < 0)
5725 5726 5727 5728 5729
        ret = -1;

    return ret;
}

5730 5731 5732
static int testConnectListAllDomains(virConnectPtr conn,
                                     virDomainPtr **domains,
                                     unsigned int flags)
5733
{
5734
    testDriverPtr privconn = conn->privateData;
5735

O
Osier Yang 已提交
5736
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
5737

5738 5739
    return virDomainObjListExport(privconn->domains, conn, domains,
                                  NULL, flags);
5740 5741
}

5742
static int
P
Peter Krempa 已提交
5743
testNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,
5744 5745 5746 5747 5748 5749 5750
                  unsigned char **cpumap,
                  unsigned int *online,
                  unsigned int flags)
{
    virCheckFlags(0, -1);

    if (cpumap) {
5751
        if (VIR_ALLOC_N(*cpumap, 1) < 0)
P
Peter Krempa 已提交
5752
            return -1;
5753 5754 5755 5756 5757 5758
        *cpumap[0] = 0x15;
    }

    if (online)
        *online = 3;

P
Peter Krempa 已提交
5759
    return  8;
5760 5761
}

5762 5763 5764 5765 5766 5767 5768 5769 5770 5771
static char *
testDomainScreenshot(virDomainPtr dom ATTRIBUTE_UNUSED,
                     virStreamPtr st,
                     unsigned int screen ATTRIBUTE_UNUSED,
                     unsigned int flags)
{
    char *ret = NULL;

    virCheckFlags(0, NULL);

5772
    if (VIR_STRDUP(ret, "image/png") < 0)
5773 5774
        return NULL;

D
Daniel P. Berrange 已提交
5775
    if (virFDStreamOpenFile(st, PKGDATADIR "/test-screenshot.png", 0, 0, O_RDONLY) < 0)
5776 5777 5778 5779 5780
        VIR_FREE(ret);

    return ret;
}

5781 5782
static int
testConnectGetCPUModelNames(virConnectPtr conn ATTRIBUTE_UNUSED,
J
Jiri Denemark 已提交
5783
                            const char *archName,
5784 5785 5786
                            char ***models,
                            unsigned int flags)
{
J
Jiri Denemark 已提交
5787 5788
    virArch arch;

5789
    virCheckFlags(0, -1);
J
Jiri Denemark 已提交
5790 5791 5792 5793 5794 5795 5796 5797

    if (!(arch = virArchFromString(archName))) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("cannot find architecture %s"),
                       archName);
        return -1;
    }

J
Jiri Denemark 已提交
5798
    return virCPUGetModels(arch, models);
5799
}
5800

C
Cole Robinson 已提交
5801 5802 5803
static int
testDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
5804
    testDriverPtr privconn = dom->conn->privateData;
C
Cole Robinson 已提交
5805
    virDomainObjPtr vm = NULL;
5806
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
5807 5808 5809 5810 5811 5812
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
                  VIR_DOMAIN_SAVE_RUNNING |
                  VIR_DOMAIN_SAVE_PAUSED, -1);

5813 5814
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828

    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);
5829
    event = virDomainEventLifecycleNewFromObj(vm,
C
Cole Robinson 已提交
5830 5831 5832 5833 5834
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
    vm->hasManagedSave = true;

    ret = 0;
5835
 cleanup:
5836
    virDomainObjEndAPI(&vm);
5837
    testObjectEventQueue(privconn, event);
C
Cole Robinson 已提交
5838 5839 5840 5841 5842 5843 5844 5845 5846

    return ret;
}


static int
testDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm;
5847
    int ret;
C
Cole Robinson 已提交
5848 5849 5850

    virCheckFlags(0, -1);

5851 5852
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5853 5854

    ret = vm->hasManagedSave;
5855

5856
    virDomainObjEndAPI(&vm);
C
Cole Robinson 已提交
5857 5858 5859 5860 5861 5862 5863 5864 5865 5866
    return ret;
}

static int
testDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm;

    virCheckFlags(0, -1);

5867 5868
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5869 5870

    vm->hasManagedSave = false;
5871

5872
    virDomainObjEndAPI(&vm);
5873
    return 0;
C
Cole Robinson 已提交
5874 5875 5876
}


5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910
/*
 * 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;
5911
    int n;
5912 5913 5914 5915 5916

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5917
        return -1;
5918 5919 5920

    n = virDomainSnapshotObjListNum(vm->snapshots, NULL, flags);

5921
    virDomainObjEndAPI(&vm);
5922 5923 5924 5925 5926 5927 5928 5929 5930 5931
    return n;
}

static int
testDomainSnapshotListNames(virDomainPtr domain,
                            char **names,
                            int nameslen,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
5932
    int n;
5933 5934 5935 5936 5937

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5938
        return -1;
5939 5940 5941 5942

    n = virDomainSnapshotObjListGetNames(vm->snapshots, NULL, names, nameslen,
                                         flags);

5943
    virDomainObjEndAPI(&vm);
5944 5945 5946 5947 5948 5949 5950 5951 5952
    return n;
}

static int
testDomainListAllSnapshots(virDomainPtr domain,
                           virDomainSnapshotPtr **snaps,
                           unsigned int flags)
{
    virDomainObjPtr vm = NULL;
5953
    int n;
5954 5955 5956 5957 5958

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5959
        return -1;
5960 5961 5962

    n = virDomainListSnapshots(vm->snapshots, NULL, domain, snaps, flags);

5963
    virDomainObjEndAPI(&vm);
5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980
    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)))
5981
        return -1;
5982 5983 5984 5985 5986 5987 5988

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    n = virDomainSnapshotObjListGetNames(vm->snapshots, snap, names, nameslen,
                                         flags);

5989
 cleanup:
5990
    virDomainObjEndAPI(&vm);
5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005
    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)))
6006
        return -1;
6007 6008 6009 6010 6011 6012

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    n = virDomainSnapshotObjListNum(vm->snapshots, snap, flags);

6013
 cleanup:
6014
    virDomainObjEndAPI(&vm);
6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030
    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)))
6031
        return -1;
6032 6033 6034 6035 6036 6037 6038

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    n = virDomainListSnapshots(vm->snapshots, snap, snapshot->domain, snaps,
                               flags);

6039
 cleanup:
6040
    virDomainObjEndAPI(&vm);
6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055
    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)))
6056
        return NULL;
6057 6058 6059 6060 6061 6062

    if (!(snap = testSnapObjFromName(vm, name)))
        goto cleanup;

    snapshot = virGetDomainSnapshot(domain, snap->def->name);

6063
 cleanup:
6064
    virDomainObjEndAPI(&vm);
6065 6066 6067 6068 6069 6070 6071 6072
    return snapshot;
}

static int
testDomainHasCurrentSnapshot(virDomainPtr domain,
                             unsigned int flags)
{
    virDomainObjPtr vm;
6073
    int ret;
6074 6075 6076 6077

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6078
        return -1;
6079 6080 6081

    ret = (vm->current_snapshot != NULL);

6082
    virDomainObjEndAPI(&vm);
6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096
    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)))
6097
        return NULL;
6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110

    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);

6111
 cleanup:
6112
    virDomainObjEndAPI(&vm);
6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125
    return parent;
}

static virDomainSnapshotPtr
testDomainSnapshotCurrent(virDomainPtr domain,
                          unsigned int flags)
{
    virDomainObjPtr vm;
    virDomainSnapshotPtr snapshot = NULL;

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
6126
        return NULL;
6127 6128 6129 6130 6131 6132 6133 6134 6135

    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);

6136
 cleanup:
6137
    virDomainObjEndAPI(&vm);
6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148
    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];
6149
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6150 6151 6152 6153

    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6154
        return NULL;
6155 6156 6157 6158 6159 6160

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    virUUIDFormat(snapshot->domain->uuid, uuidstr);

6161
    xml = virDomainSnapshotDefFormat(uuidstr, snap->def, privconn->caps,
6162
                                     privconn->xmlopt,
6163 6164
                                     virDomainDefFormatConvertXMLFlags(flags),
                                     0);
6165

6166
 cleanup:
6167
    virDomainObjEndAPI(&vm);
6168 6169 6170 6171 6172 6173 6174 6175
    return xml;
}

static int
testDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6176
    int ret;
6177 6178 6179 6180

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6181
        return -1;
6182 6183 6184 6185

    ret = (vm->current_snapshot &&
           STREQ(snapshot->name, vm->current_snapshot->def->name));

6186
    virDomainObjEndAPI(&vm);
6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200
    return ret;
}


static int
testDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot,
                              unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6201
        return -1;
6202

C
Cole Robinson 已提交
6203
    if (!testSnapObjFromSnapshot(vm, snapshot))
6204 6205 6206 6207
        goto cleanup;

    ret = 1;

6208
 cleanup:
6209
    virDomainObjEndAPI(&vm);
6210 6211 6212
    return ret;
}

6213 6214 6215 6216 6217 6218
static int
testDomainSnapshotAlignDisks(virDomainObjPtr vm,
                             virDomainSnapshotDefPtr def,
                             unsigned int flags)
{
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
E
Eric Blake 已提交
6219
    bool align_match = true;
6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247

    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)
{
6248
    testDriverPtr privconn = domain->conn->privateData;
6249 6250 6251 6252
    virDomainObjPtr vm = NULL;
    virDomainSnapshotDefPtr def = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr snapshot = NULL;
6253
    virObjectEventPtr event = NULL;
6254
    char *xml = NULL;
6255 6256
    bool update_current = true;
    bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
6257 6258 6259 6260 6261 6262 6263 6264
    unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;

    /*
     * DISK_ONLY: Not implemented yet
     * REUSE_EXT: Not implemented yet
     *
     * NO_METADATA: Explicitly not implemented
     *
6265
     * REDEFINE + CURRENT: Implemented
6266 6267 6268 6269 6270 6271
     * HALT: Implemented
     * QUIESCE: Nothing to do
     * ATOMIC: Nothing to do
     * LIVE: Nothing to do
     */
    virCheckFlags(
6272 6273
        VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
        VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
6274 6275 6276 6277 6278
        VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
        VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
        VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
        VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, NULL);

6279 6280 6281 6282 6283
    if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)))
        update_current = false;
    if (redefine)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;

6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298
    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;

6299
    if (redefine) {
C
Cole Robinson 已提交
6300
        if (virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
6301
                                          privconn->xmlopt,
C
Cole Robinson 已提交
6302
                                          &update_current, flags) < 0)
6303 6304 6305 6306 6307
            goto cleanup;
    } else {
        if (!(def->dom = virDomainDefCopy(vm->def,
                                          privconn->caps,
                                          privconn->xmlopt,
6308
                                          NULL,
6309 6310
                                          true)))
            goto cleanup;
6311

6312
        if (testDomainSnapshotAlignDisks(vm, def, flags) < 0)
6313 6314 6315
            goto cleanup;
    }

6316 6317 6318 6319
    if (!snap) {
        if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
            goto cleanup;
        def = NULL;
6320 6321
    }

6322 6323 6324 6325 6326 6327 6328 6329 6330 6331
    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);
6332
            event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
6333 6334 6335
                                    VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
        }
    }
6336 6337

    snapshot = virGetDomainSnapshot(domain, snap->def->name);
6338
 cleanup:
6339 6340 6341 6342
    VIR_FREE(xml);
    if (vm) {
        if (snapshot) {
            virDomainSnapshotObjPtr other;
6343 6344
            if (update_current)
                vm->current_snapshot = snap;
6345 6346 6347 6348 6349 6350 6351
            other = virDomainSnapshotFindByName(vm->snapshots,
                                                snap->def->parent);
            snap->parent = other;
            other->nchildren++;
            snap->sibling = other->first_child;
            other->first_child = snap;
        }
6352
        virDomainObjEndAPI(&vm);
6353
    }
6354
    testObjectEventQueue(privconn, event);
6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366
    virDomainSnapshotDefFree(def);
    return snapshot;
}


typedef struct _testSnapRemoveData testSnapRemoveData;
typedef testSnapRemoveData *testSnapRemoveDataPtr;
struct _testSnapRemoveData {
    virDomainObjPtr vm;
    bool current;
};

6367
static int
6368
testDomainSnapshotDiscardAll(void *payload,
6369 6370
                             const void *name ATTRIBUTE_UNUSED,
                             void *data)
6371 6372 6373 6374 6375 6376 6377
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapRemoveDataPtr curr = data;

    if (snap->def->current)
        curr->current = true;
    virDomainSnapshotObjListRemove(curr->vm->snapshots, snap);
6378
    return 0;
6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389
}

typedef struct _testSnapReparentData testSnapReparentData;
typedef testSnapReparentData *testSnapReparentDataPtr;
struct _testSnapReparentData {
    virDomainSnapshotObjPtr parent;
    virDomainObjPtr vm;
    int err;
    virDomainSnapshotObjPtr last;
};

6390
static int
6391 6392 6393 6394 6395 6396 6397
testDomainSnapshotReparentChildren(void *payload,
                                   const void *name ATTRIBUTE_UNUSED,
                                   void *data)
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapReparentDataPtr rep = data;

6398
    if (rep->err < 0)
6399
        return 0;
6400 6401 6402 6403 6404 6405 6406

    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;
6407
        return 0;
6408 6409 6410 6411
    }

    if (!snap->sibling)
        rep->last = snap;
6412
    return 0;
6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441
}

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) {
6442
            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)
6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485
                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;
6486
 cleanup:
6487
    virDomainObjEndAPI(&vm);
6488 6489 6490 6491 6492 6493 6494
    return ret;
}

static int
testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                           unsigned int flags)
{
6495
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6496 6497
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
6498 6499
    virObjectEventPtr event = NULL;
    virObjectEventPtr event2 = NULL;
6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562
    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;
6563 6564
    config = virDomainDefCopy(snap->def->dom, privconn->caps,
                              privconn->xmlopt, NULL, true);
6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576
    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.  */
6577 6578
            if (!virDomainDefCheckABIStability(vm->def, config,
                                               privconn->xmlopt)) {
6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591
                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);
6592
                event = virDomainEventLifecycleNewFromObj(vm,
6593 6594
                            VIR_DOMAIN_EVENT_STOPPED,
                            VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
6595
                testObjectEventQueue(privconn, event);
6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606
                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. */
6607
                event = virDomainEventLifecycleNewFromObj(vm,
6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620
                                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;
6621
            event = virDomainEventLifecycleNewFromObj(vm,
6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634
                                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 */
6635
                event2 = virDomainEventLifecycleNewFromObj(vm,
6636 6637 6638 6639 6640
                                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 已提交
6641
            virObjectUnref(event);
6642 6643 6644 6645
            event = NULL;

            if (was_stopped) {
                /* Transition 2 */
6646
                event = virDomainEventLifecycleNewFromObj(vm,
6647 6648 6649 6650
                                VIR_DOMAIN_EVENT_STARTED,
                                VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            } else if (was_running) {
                /* Transition 8 */
6651
                event = virDomainEventLifecycleNewFromObj(vm,
6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663
                                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);
6664
            event = virDomainEventLifecycleNewFromObj(vm,
6665 6666 6667 6668 6669 6670 6671 6672 6673
                                    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;

6674
            testObjectEventQueue(privconn, event);
6675
            event = virDomainEventLifecycleNewFromObj(vm,
6676 6677 6678
                            VIR_DOMAIN_EVENT_STARTED,
                            VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            if (paused) {
6679
                event2 = virDomainEventLifecycleNewFromObj(vm,
6680 6681 6682 6683 6684 6685 6686 6687
                                VIR_DOMAIN_EVENT_SUSPENDED,
                                VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
            }
        }
    }

    vm->current_snapshot = snap;
    ret = 0;
6688
 cleanup:
6689
    if (event) {
6690
        testObjectEventQueue(privconn, event);
6691
        testObjectEventQueue(privconn, event2);
C
Cole Robinson 已提交
6692
    } else {
C
Cédric Bosdonnat 已提交
6693
        virObjectUnref(event2);
6694
    }
6695
    virDomainObjEndAPI(&vm);
6696 6697 6698 6699 6700

    return ret;
}


6701

6702
static virHypervisorDriver testHypervisorDriver = {
6703
    .name = "Test",
6704 6705 6706
    .connectOpen = testConnectOpen, /* 0.1.1 */
    .connectClose = testConnectClose, /* 0.1.1 */
    .connectGetVersion = testConnectGetVersion, /* 0.1.1 */
6707
    .connectGetHostname = testConnectGetHostname, /* 0.6.3 */
6708
    .connectGetMaxVcpus = testConnectGetMaxVcpus, /* 0.3.2 */
6709
    .nodeGetInfo = testNodeGetInfo, /* 0.1.1 */
6710
    .nodeGetCPUStats = testNodeGetCPUStats, /* 2.3.0 */
6711
    .nodeGetFreeMemory = testNodeGetFreeMemory, /* 2.3.0 */
6712
    .nodeGetFreePages = testNodeGetFreePages, /* 2.3.0 */
6713
    .connectGetCapabilities = testConnectGetCapabilities, /* 0.2.1 */
6714
    .connectGetSysinfo = testConnectGetSysinfo, /* 2.3.0 */
6715
    .connectGetType = testConnectGetType, /* 2.3.0 */
6716 6717 6718
    .connectListDomains = testConnectListDomains, /* 0.1.1 */
    .connectNumOfDomains = testConnectNumOfDomains, /* 0.1.1 */
    .connectListAllDomains = testConnectListAllDomains, /* 0.9.13 */
6719
    .domainCreateXML = testDomainCreateXML, /* 0.1.4 */
6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733
    .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 */
6734 6735
    .domainGetState = testDomainGetState, /* 0.9.2 */
    .domainSave = testDomainSave, /* 0.3.2 */
6736
    .domainSaveFlags = testDomainSaveFlags, /* 0.9.4 */
6737
    .domainRestore = testDomainRestore, /* 0.3.2 */
6738
    .domainRestoreFlags = testDomainRestoreFlags, /* 0.9.4 */
6739
    .domainCoreDump = testDomainCoreDump, /* 0.3.2 */
6740
    .domainCoreDumpWithFormat = testDomainCoreDumpWithFormat, /* 1.2.3 */
6741
    .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */
6742 6743 6744 6745
    .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */
    .domainGetVcpusFlags = testDomainGetVcpusFlags, /* 0.8.5 */
    .domainPinVcpu = testDomainPinVcpu, /* 0.7.3 */
    .domainGetVcpus = testDomainGetVcpus, /* 0.7.3 */
6746
    .domainGetVcpuPinInfo = testDomainGetVcpuPinInfo, /* 1.2.18 */
6747 6748
    .domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
    .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
6749 6750
    .connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
    .connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
6751 6752 6753
    .domainCreate = testDomainCreate, /* 0.1.11 */
    .domainCreateWithFlags = testDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = testDomainDefineXML, /* 0.1.11 */
6754
    .domainDefineXMLFlags = testDomainDefineXMLFlags, /* 1.2.12 */
6755
    .domainUndefine = testDomainUndefine, /* 0.1.11 */
6756
    .domainUndefineFlags = testDomainUndefineFlags, /* 0.9.4 */
6757 6758 6759
    .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
    .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
    .domainGetSchedulerType = testDomainGetSchedulerType, /* 0.3.2 */
6760 6761 6762 6763
    .domainGetSchedulerParameters = testDomainGetSchedulerParameters, /* 0.3.2 */
    .domainGetSchedulerParametersFlags = testDomainGetSchedulerParametersFlags, /* 0.9.2 */
    .domainSetSchedulerParameters = testDomainSetSchedulerParameters, /* 0.3.2 */
    .domainSetSchedulerParametersFlags = testDomainSetSchedulerParametersFlags, /* 0.9.2 */
6764 6765 6766
    .domainBlockStats = testDomainBlockStats, /* 0.7.0 */
    .domainInterfaceStats = testDomainInterfaceStats, /* 0.7.0 */
    .nodeGetCellsFreeMemory = testNodeGetCellsFreeMemory, /* 0.4.2 */
6767 6768 6769 6770
    .connectDomainEventRegister = testConnectDomainEventRegister, /* 0.6.0 */
    .connectDomainEventDeregister = testConnectDomainEventDeregister, /* 0.6.0 */
    .connectIsEncrypted = testConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = testConnectIsSecure, /* 0.7.3 */
6771 6772 6773
    .domainIsActive = testDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = testDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = testDomainIsUpdated, /* 0.8.6 */
6774 6775 6776
    .connectDomainEventRegisterAny = testConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = testConnectDomainEventDeregisterAny, /* 0.8.0 */
    .connectIsAlive = testConnectIsAlive, /* 0.9.8 */
6777
    .nodeGetCPUMap = testNodeGetCPUMap, /* 1.0.0 */
6778
    .domainScreenshot = testDomainScreenshot, /* 1.0.5 */
6779 6780
    .domainGetMetadata = testDomainGetMetadata, /* 1.1.3 */
    .domainSetMetadata = testDomainSetMetadata, /* 1.1.3 */
6781
    .connectGetCPUModelNames = testConnectGetCPUModelNames, /* 1.1.3 */
6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798
    .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 */
6799 6800 6801
    .domainSnapshotCreateXML = testDomainSnapshotCreateXML, /* 1.1.4 */
    .domainRevertToSnapshot = testDomainRevertToSnapshot, /* 1.1.4 */
    .domainSnapshotDelete = testDomainSnapshotDelete, /* 1.1.4 */
6802

E
Eric Blake 已提交
6803
    .connectBaselineCPU = testConnectBaselineCPU, /* 1.2.0 */
6804 6805 6806
};

static virNetworkDriver testNetworkDriver = {
6807 6808 6809 6810 6811
    .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 */
6812 6813
    .connectNetworkEventRegisterAny = testConnectNetworkEventRegisterAny, /* 1.2.1 */
    .connectNetworkEventDeregisterAny = testConnectNetworkEventDeregisterAny, /* 1.2.1 */
6814 6815 6816 6817
    .networkLookupByUUID = testNetworkLookupByUUID, /* 0.3.2 */
    .networkLookupByName = testNetworkLookupByName, /* 0.3.2 */
    .networkCreateXML = testNetworkCreateXML, /* 0.3.2 */
    .networkDefineXML = testNetworkDefineXML, /* 0.3.2 */
6818
    .networkUndefine = testNetworkUndefine, /* 0.3.2 */
6819
    .networkUpdate = testNetworkUpdate, /* 0.10.2 */
6820
    .networkCreate = testNetworkCreate, /* 0.3.2 */
6821 6822 6823 6824 6825 6826 6827
    .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 */
6828 6829
};

L
Laine Stump 已提交
6830
static virInterfaceDriver testInterfaceDriver = {
6831 6832 6833 6834 6835 6836
    .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 */
6837 6838 6839 6840 6841 6842
    .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 */
6843 6844 6845
    .interfaceChangeBegin = testInterfaceChangeBegin,   /* 0.9.2 */
    .interfaceChangeCommit = testInterfaceChangeCommit,  /* 0.9.2 */
    .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */
L
Laine Stump 已提交
6846 6847 6848
};


6849
static virStorageDriver testStorageDriver = {
6850 6851 6852 6853 6854 6855
    .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 */
6856 6857
    .connectStoragePoolEventRegisterAny = testConnectStoragePoolEventRegisterAny, /* 2.0.0 */
    .connectStoragePoolEventDeregisterAny = testConnectStoragePoolEventDeregisterAny, /* 2.0.0 */
6858 6859 6860
    .storagePoolLookupByName = testStoragePoolLookupByName, /* 0.5.0 */
    .storagePoolLookupByUUID = testStoragePoolLookupByUUID, /* 0.5.0 */
    .storagePoolLookupByVolume = testStoragePoolLookupByVolume, /* 0.5.0 */
6861 6862
    .storagePoolCreateXML = testStoragePoolCreateXML, /* 0.5.0 */
    .storagePoolDefineXML = testStoragePoolDefineXML, /* 0.5.0 */
6863 6864
    .storagePoolBuild = testStoragePoolBuild, /* 0.5.0 */
    .storagePoolUndefine = testStoragePoolUndefine, /* 0.5.0 */
6865
    .storagePoolCreate = testStoragePoolCreate, /* 0.5.0 */
6866 6867 6868 6869 6870 6871 6872
    .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 */
6873
    .storagePoolNumOfVolumes = testStoragePoolNumOfVolumes, /* 0.5.0 */
6874 6875 6876
    .storagePoolListVolumes = testStoragePoolListVolumes, /* 0.5.0 */
    .storagePoolListAllVolumes = testStoragePoolListAllVolumes, /* 0.10.2 */

6877 6878 6879 6880 6881 6882 6883 6884 6885
    .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 */
6886 6887
    .storagePoolIsActive = testStoragePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = testStoragePoolIsPersistent, /* 0.7.3 */
6888 6889
};

6890
static virNodeDeviceDriver testNodeDeviceDriver = {
6891 6892
    .connectNodeDeviceEventRegisterAny = testConnectNodeDeviceEventRegisterAny, /* 2.2.0 */
    .connectNodeDeviceEventDeregisterAny = testConnectNodeDeviceEventDeregisterAny, /* 2.2.0 */
6893 6894 6895 6896 6897 6898 6899 6900 6901
    .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 */
6902 6903
};

6904 6905 6906 6907 6908 6909 6910 6911
static virConnectDriver testConnectDriver = {
    .hypervisorDriver = &testHypervisorDriver,
    .interfaceDriver = &testInterfaceDriver,
    .networkDriver = &testNetworkDriver,
    .nodeDeviceDriver = &testNodeDeviceDriver,
    .nwfilterDriver = NULL,
    .secretDriver = NULL,
    .storageDriver = &testStorageDriver,
6912 6913
};

6914 6915 6916 6917 6918 6919 6920 6921
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
6922 6923
    return virRegisterConnectDriver(&testConnectDriver,
                                    false);
6924
}