test_driver.c 201.7 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"
44
#include "network_conf.h"
L
Laine Stump 已提交
45
#include "interface_conf.h"
46
#include "domain_conf.h"
47
#include "domain_event.h"
48
#include "network_event.h"
49
#include "snapshot_conf.h"
50
#include "fdstream.h"
C
Cole Robinson 已提交
51
#include "storage_conf.h"
52
#include "storage_event.h"
53
#include "node_device_conf.h"
J
John Ferlan 已提交
54
#include "virnodedeviceobj.h"
55
#include "node_device_event.h"
56
#include "virxml.h"
57
#include "virthread.h"
58
#include "virlog.h"
E
Eric Blake 已提交
59
#include "virfile.h"
60
#include "virtypedparam.h"
61
#include "virrandom.h"
62
#include "virstring.h"
63
#include "cpu/cpu.h"
64
#include "virauth.h"
65
#include "viratomic.h"
66
#include "virdomainobjlist.h"
J
John Ferlan 已提交
67
#include "virinterfaceobj.h"
68
#include "virhostcpu.h"
69

70 71
#define VIR_FROM_THIS VIR_FROM_TEST

72 73
VIR_LOG_INIT("test.test_driver");

74

75 76 77 78
#define MAX_CPUS 128

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

#define MAX_CELLS 128
87

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

95
struct _testDriver {
96
    virMutex lock;
97

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

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

112 113 114 115 116 117 118 119 120 121
    /* 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;
122
    virObjectEventStatePtr eventState;
123
};
124 125
typedef struct _testDriver testDriver;
typedef testDriver *testDriverPtr;
126

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

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

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

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

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

    VIR_FREE(driver);
}
164

165

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

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

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

    virObjectEventStateQueue(driver->eventState, event);
}

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

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

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

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

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

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

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

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

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

297 298 299
    *data = nsdata;
    return 0;

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

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

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

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

324 325 326 327 328 329
    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;

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

335 336 337 338 339 340 341
        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;
342 343 344 345

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

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

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

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

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

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

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

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

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

390
    return caps;
391

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

397

398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
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;
    }

416
    if (!(ret->xmlopt = virDomainXMLOptionNew(NULL, NULL, &ns)) ||
417 418 419 420 421
        !(ret->eventState = virObjectEventStateNew()) ||
        !(ret->domains = virDomainObjListNew()) ||
        !(ret->networks = virNetworkObjListNew()))
        goto error;

422
    virAtomicIntSet(&ret->nextDomID, 1);
423 424 425 426 427 428 429 430 431

    return ret;

 error:
    testDriverFree(ret);
    return NULL;
}


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

C
Cole Robinson 已提交
540

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

564
static const unsigned long long defaultPoolCap = (100 * 1024 * 1024 * 1024ull);
565
static const unsigned long long defaultPoolAlloc;
C
Cole Robinson 已提交
566

567
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool);
568
static int testNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
569

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

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

    return vm;
}

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

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

599
        if (virAsprintf(&ifname, "testnet%d", ifctr) < 0)
600 601 602
            return NULL;

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

        if (!found)
            return ifname;
613
        VIR_FREE(ifname);
614 615
    }

616 617
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Exceeded max iface limit %d"), maxif);
618 619 620
    return NULL;
}

621
static int
622
testDomainGenerateIfnames(virDomainDefPtr domdef)
623
{
624
    size_t i = 0;
625 626 627 628 629 630

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

631
        ifname = testDomainGenerateIfname(domdef);
632
        if (!ifname)
633
            return -1;
634 635 636 637

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

638
    return 0;
639 640
}

641

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

650 651 652 653
    if (domain)
        domain->id = -1;
}

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

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

665
    if (virDomainObjSetDefTransient(privconn->caps,
666
                                    privconn->xmlopt,
667
                                    dom) < 0) {
668 669 670
        goto cleanup;
    }

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

679

680
static char *testBuildFilename(const char *relativeTo,
681 682
                               const char *filename)
{
683 684
    char *offset;
    int baseLen;
685 686
    char *ret;

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

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

C
Cole Robinson 已提交
712 713 714 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
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;
    }

743
 error:
C
Cole Robinson 已提交
744 745 746 747 748
    xmlFreeDoc(doc);
    VIR_FREE(absFile);
    return ret;
}

749 750 751
static int
testParseNodeInfo(virNodeInfoPtr nodeInfo, xmlXPathContextPtr ctxt)
{
752
    char *str;
753 754
    long l;
    int ret;
755

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

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

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

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

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

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

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

832
    return 0;
833
 error:
834 835 836
    return -1;
}

837
static int
838
testParseDomainSnapshots(testDriverPtr privconn,
839 840 841 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
                         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;
889
 error:
890 891 892
    return ret;
}

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

    num = virXPathNodeSet("/node/domain", ctxt, &nodes);
904
    if (num < 0)
905 906
        goto error;

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

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

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

929 930 931 932 933
        if (testParseDomainSnapshots(privconn, obj, file, ctxt) < 0) {
            virObjectUnlock(obj);
            goto error;
        }

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

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

949
        virObjectUnlock(obj);
950
    }
951

952
    ret = 0;
953
 error:
954 955 956 957 958
    VIR_FREE(nodes);
    return ret;
}

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

    num = virXPathNodeSet("/node/network", ctxt, &nodes);
969
    if (num < 0)
970
        goto error;
971 972

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

C
Cole Robinson 已提交
978 979 980
        def = virNetworkDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
981

982
        if (!(obj = virNetworkAssignDef(privconn->networks, def, 0))) {
983 984
            virNetworkDefFree(def);
            goto error;
985
        }
986 987

        obj->active = 1;
988
        virNetworkObjEndAPI(&obj);
989
    }
990

991
    ret = 0;
992
 error:
993 994 995 996 997
    VIR_FREE(nodes);
    return ret;
}

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

    num = virXPathNodeSet("/node/interface", ctxt, &nodes);
1008
    if (num < 0)
L
Laine Stump 已提交
1009
        goto error;
1010 1011

    for (i = 0; i < num; i++) {
L
Laine Stump 已提交
1012
        virInterfaceDefPtr def;
C
Cole Robinson 已提交
1013 1014 1015 1016
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "interface");
        if (!node)
            goto error;
L
Laine Stump 已提交
1017

C
Cole Robinson 已提交
1018 1019 1020
        def = virInterfaceDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
1021

1022
        if (!(obj = virInterfaceObjAssignDef(&privconn->ifaces, def))) {
L
Laine Stump 已提交
1023 1024 1025
            virInterfaceDefFree(def);
            goto error;
        }
1026

1027 1028 1029 1030 1031
        obj->active = 1;
        virInterfaceObjUnlock(obj);
    }

    ret = 0;
1032
 error:
1033 1034 1035 1036 1037
    VIR_FREE(nodes);
    return ret;
}

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

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

    num = virXPathNodeSet(vol_xpath, ctxt, &nodes);
    VIR_FREE(vol_xpath);
1055
    if (num < 0)
1056 1057 1058
        goto error;

    for (i = 0; i < num; i++) {
C
Cole Robinson 已提交
1059 1060 1061 1062
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "volume");
        if (!node)
            goto error;
1063

1064
        def = virStorageVolDefParseNode(pool->def, ctxt->doc, node, 0);
C
Cole Robinson 已提交
1065 1066
        if (!def)
            goto error;
1067 1068 1069 1070 1071 1072 1073 1074 1075 1076

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

        if (!def->key && VIR_STRDUP(def->key, def->target.path) < 0)
            goto error;
1077 1078
        if (VIR_APPEND_ELEMENT_COPY(pool->volumes.objs, pool->volumes.count, def) < 0)
            goto error;
1079

1080
        pool->def->allocation += def->target.allocation;
1081 1082 1083
        pool->def->available = (pool->def->capacity -
                                pool->def->allocation);
        def = NULL;
L
Laine Stump 已提交
1084 1085
    }

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

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

    num = virXPathNodeSet("/node/pool", ctxt, &nodes);
1104
    if (num < 0)
C
Cole Robinson 已提交
1105
        goto error;
1106 1107

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

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

1118
        if (!(obj = virStoragePoolObjAssignDef(&privconn->pools,
C
Cole Robinson 已提交
1119 1120 1121 1122 1123
                                                def))) {
            virStoragePoolDefFree(def);
            goto error;
        }

1124 1125
        if (testStoragePoolObjSetDefaults(obj) == -1) {
            virStoragePoolObjUnlock(obj);
C
Cole Robinson 已提交
1126
            goto error;
1127
        }
1128
        obj->active = 1;
1129 1130

        /* Find storage volumes */
C
Cole Robinson 已提交
1131
        if (testOpenVolumesForPool(file, ctxt, obj, i+1) < 0) {
1132
            virStoragePoolObjUnlock(obj);
1133 1134 1135
            goto error;
        }

1136
        virStoragePoolObjUnlock(obj);
C
Cole Robinson 已提交
1137 1138
    }

1139
    ret = 0;
1140
 error:
1141 1142 1143 1144 1145
    VIR_FREE(nodes);
    return ret;
}

static int
1146
testParseNodedevs(testDriverPtr privconn,
C
Cole Robinson 已提交
1147 1148
                  const char *file,
                  xmlXPathContextPtr ctxt)
1149 1150 1151 1152 1153 1154 1155
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virNodeDeviceObjPtr obj;

    num = virXPathNodeSet("/node/device", ctxt, &nodes);
1156
    if (num < 0)
1157
        goto error;
1158 1159

    for (i = 0; i < num; i++) {
1160
        virNodeDeviceDefPtr def;
C
Cole Robinson 已提交
1161 1162 1163 1164
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                  "nodedev");
        if (!node)
            goto error;
1165

C
Cole Robinson 已提交
1166 1167 1168
        def = virNodeDeviceDefParseNode(ctxt->doc, node, 0, NULL);
        if (!def)
            goto error;
1169

1170
        if (!(obj = virNodeDeviceObjAssignDef(&privconn->devs, def))) {
1171 1172 1173
            virNodeDeviceDefFree(def);
            goto error;
        }
1174 1175 1176 1177 1178

        virNodeDeviceObjUnlock(obj);
    }

    ret = 0;
1179
 error:
1180 1181 1182 1183
    VIR_FREE(nodes);
    return ret;
}

1184
static int
1185
testParseAuthUsers(testDriverPtr privconn,
1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218
                   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;
1219
 error:
1220 1221 1222
    VIR_FREE(nodes);
    return ret;
}
1223

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

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

    return 0;
 error:
    return -1;
}

1255 1256
/* No shared state between simultaneous test connections initialized
 * from a file.  */
1257 1258 1259 1260 1261
static int
testOpenFromFile(virConnectPtr conn, const char *file)
{
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
1262
    testDriverPtr privconn;
1263

1264
    if (!(privconn = testDriverNew()))
1265
        return VIR_DRV_OPEN_ERROR;
1266

1267 1268 1269 1270 1271 1272
    testDriverLock(privconn);
    conn->privateData = privconn;

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

1273
    if (!(doc = virXMLParseFileCtxt(file, &ctxt)))
1274 1275 1276 1277 1278
        goto error;

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

C
Cole Robinson 已提交
1279
    if (testOpenParse(privconn, file, ctxt) < 0)
1280
        goto error;
1281

J
Jim Meyering 已提交
1282
    xmlXPathFreeContext(ctxt);
1283
    xmlFreeDoc(doc);
1284
    testDriverUnlock(privconn);
1285

1286
    return 0;
1287 1288

 error:
J
Jim Meyering 已提交
1289
    xmlXPathFreeContext(ctxt);
1290
    xmlFreeDoc(doc);
1291
    testDriverFree(privconn);
1292
    conn->privateData = NULL;
1293
    return VIR_DRV_OPEN_ERROR;
1294 1295
}

1296 1297 1298 1299 1300 1301 1302
/* 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;
1303 1304
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
1305
    size_t i;
1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322

    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;
1323 1324 1325 1326
    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;
1327
    }
1328
    for (i = 0; i < 16; i++) {
1329 1330 1331
        virBitmapPtr siblings = virBitmapNew(16);
        if (!siblings)
            goto error;
1332 1333 1334 1335 1336
        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;
1337 1338 1339 1340 1341
    }

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

1342 1343
    if (!(doc = virXMLParseStringCtxt(defaultConnXML,
                                      _("(test driver)"), &ctxt)))
1344 1345
        goto error;

1346
    if (testOpenParse(privconn, NULL, ctxt) < 0)
1347 1348 1349 1350
        goto error;

    defaultConn = privconn;

1351 1352
    xmlXPathFreeContext(ctxt);
    xmlFreeDoc(doc);
1353 1354 1355 1356 1357 1358
    virMutexUnlock(&defaultLock);

    return VIR_DRV_OPEN_SUCCESS;

 error:
    testDriverFree(privconn);
1359 1360
    xmlXPathFreeContext(ctxt);
    xmlFreeDoc(doc);
1361 1362 1363 1364 1365 1366
    conn->privateData = NULL;
    defaultConnections--;
    virMutexUnlock(&defaultLock);
    return VIR_DRV_OPEN_ERROR;
}

1367 1368 1369 1370
static int
testConnectAuthenticate(virConnectPtr conn,
                        virConnectAuthPtr auth)
{
1371
    testDriverPtr privconn = conn->privateData;
1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395
    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;

1396
 found_user:
1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415
    /* 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;
1416
 cleanup:
1417 1418 1419 1420
    VIR_FREE(username);
    VIR_FREE(password);
    return ret;
}
1421

1422
static virDrvOpenStatus testConnectOpen(virConnectPtr conn,
1423
                                        virConnectAuthPtr auth,
1424
                                        virConfPtr conf ATTRIBUTE_UNUSED,
1425
                                        unsigned int flags)
1426
{
1427
    int ret;
1428

E
Eric Blake 已提交
1429 1430
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

1431
    if (!conn->uri)
1432
        return VIR_DRV_OPEN_DECLINED;
1433

1434
    if (!conn->uri->scheme || STRNEQ(conn->uri->scheme, "test"))
1435
        return VIR_DRV_OPEN_DECLINED;
1436

1437
    /* Remote driver should handle these. */
1438
    if (conn->uri->server)
1439 1440
        return VIR_DRV_OPEN_DECLINED;

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

1450
    if (STREQ(conn->uri->path, "/default"))
1451 1452
        ret = testOpenDefault(conn);
    else
1453
        ret = testOpenFromFile(conn,
1454
                               conn->uri->path);
1455

1456 1457 1458
    if (ret != VIR_DRV_OPEN_SUCCESS)
        return ret;

1459 1460 1461 1462
    /* Fake authentication. */
    if (testConnectAuthenticate(conn, auth) < 0)
        return VIR_DRV_OPEN_ERROR;

1463
    return VIR_DRV_OPEN_SUCCESS;
1464 1465
}

1466
static int testConnectClose(virConnectPtr conn)
1467
{
1468
    testDriverPtr privconn = conn->privateData;
1469
    bool dflt = false;
1470

1471 1472
    if (privconn == defaultConn) {
        dflt = true;
1473 1474 1475 1476 1477 1478 1479
        virMutexLock(&defaultLock);
        if (--defaultConnections) {
            virMutexUnlock(&defaultLock);
            return 0;
        }
    }

1480
    testDriverLock(privconn);
1481
    testDriverFree(privconn);
1482 1483 1484

    if (dflt) {
        defaultConn = NULL;
1485
        virMutexUnlock(&defaultLock);
1486 1487
    }

1488
    conn->privateData = NULL;
1489
    return 0;
1490 1491
}

1492 1493
static int testConnectGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
                                 unsigned long *hvVer)
1494
{
1495
    *hvVer = 2;
1496
    return 0;
1497 1498
}

1499 1500 1501 1502 1503 1504
static char *testConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return virGetHostname();
}


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

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

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

1520 1521
static int testConnectGetMaxVcpus(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type ATTRIBUTE_UNUSED)
1522 1523 1524 1525
{
    return 32;
}

1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540
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;
}

1541 1542
static int testNodeGetInfo(virConnectPtr conn,
                           virNodeInfoPtr info)
1543
{
1544
    testDriverPtr privconn = conn->privateData;
1545
    testDriverLock(privconn);
1546
    memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo));
1547
    testDriverUnlock(privconn);
1548
    return 0;
1549 1550
}

1551
static char *testConnectGetCapabilities(virConnectPtr conn)
1552
{
1553
    testDriverPtr privconn = conn->privateData;
1554
    char *xml;
1555
    testDriverLock(privconn);
1556
    xml = virCapabilitiesFormatXML(privconn->caps);
1557
    testDriverUnlock(privconn);
1558
    return xml;
1559 1560
}

1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580
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;
}

1581 1582 1583 1584 1585 1586
static const char *
testConnectGetType(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return "TEST";
}

1587
static int testConnectNumOfDomains(virConnectPtr conn)
1588
{
1589
    testDriverPtr privconn = conn->privateData;
1590
    int count;
1591

1592
    testDriverLock(privconn);
1593
    count = virDomainObjListNumOfDomains(privconn->domains, true, NULL, NULL);
1594
    testDriverUnlock(privconn);
1595

1596
    return count;
1597 1598
}

1599 1600 1601
static int testDomainIsActive(virDomainPtr dom)
{
    virDomainObjPtr obj;
1602
    int ret;
1603

1604 1605
    if (!(obj = testDomObjFromDomain(dom)))
        return -1;
1606

1607 1608
    ret = virDomainObjIsActive(obj);
    virDomainObjEndAPI(&obj);
1609 1610 1611 1612 1613 1614
    return ret;
}

static int testDomainIsPersistent(virDomainPtr dom)
{
    virDomainObjPtr obj;
1615 1616 1617 1618
    int ret;

    if (!(obj = testDomObjFromDomain(dom)))
        return -1;
1619 1620 1621

    ret = obj->persistent;

1622
    virDomainObjEndAPI(&obj);
1623 1624 1625
    return ret;
}

1626 1627 1628 1629 1630
static int testDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
{
    return 0;
}

1631
static virDomainPtr
1632
testDomainCreateXML(virConnectPtr conn, const char *xml,
1633
                      unsigned int flags)
1634
{
1635
    testDriverPtr privconn = conn->privateData;
1636
    virDomainPtr ret = NULL;
1637
    virDomainDefPtr def;
1638
    virDomainObjPtr dom = NULL;
1639
    virObjectEventPtr event = NULL;
1640
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
1641

1642 1643 1644
    virCheckFlags(VIR_DOMAIN_START_VALIDATE, NULL);

    if (flags & VIR_DOMAIN_START_VALIDATE)
1645
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
1646

1647
    testDriverLock(privconn);
1648
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
1649
                                       NULL, parse_flags)) == NULL)
1650
        goto cleanup;
1651

1652
    if (testDomainGenerateIfnames(def) < 0)
1653
        goto cleanup;
1654
    if (!(dom = virDomainObjListAdd(privconn->domains,
1655
                                    def,
1656
                                    privconn->xmlopt,
1657
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
1658 1659
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
1660 1661
        goto cleanup;
    def = NULL;
1662

1663 1664 1665 1666 1667
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_BOOTED) < 0) {
        if (!dom->persistent) {
            virDomainObjListRemove(privconn->domains, dom);
            dom = NULL;
        }
1668
        goto cleanup;
1669
    }
1670

1671
    event = virDomainEventLifecycleNewFromObj(dom,
1672 1673 1674
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);

1675
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1676
    if (ret)
1677
        ret->id = dom->def->id;
1678

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


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

1696
    if (!(dom = virDomainObjListFindByID(privconn->domains, id))) {
1697
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1698
        goto cleanup;
1699 1700
    }

1701
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1702 1703 1704
    if (ret)
        ret->id = dom->def->id;

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

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

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

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

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);
1746 1747 1748
    if (ret)
        ret->id = dom->def->id;

1749
 cleanup:
1750
    virDomainObjEndAPI(&dom);
1751
    return ret;
1752 1753
}

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

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

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

1771
    if (!(privdom = testDomObjFromDomain(domain)))
1772
        goto cleanup;
1773

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

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

1785 1786
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
1787 1788

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

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

1802 1803
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1804

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

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

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

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

1832 1833
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1834

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

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

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

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

1862 1863
    virCheckFlags(0, -1);

1864

1865
    if (!(privdom = testDomObjFromDomain(domain)))
1866
        goto cleanup;
1867

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

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

1879 1880
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
1881

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

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

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


1904
    if (!(privdom = testDomObjFromDomain(domain)))
1905
        goto cleanup;
1906

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

J
Jiri Denemark 已提交
1913 1914 1915
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTDOWN,
                         VIR_DOMAIN_SHUTDOWN_USER);

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

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

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

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

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

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

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

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

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

1967 1968
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1969 1970

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

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

1983
 cleanup:
1984
    virDomainObjEndAPI(&privdom);
1985
    return ret;
1986 1987
}

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

    virCheckFlags(0, -1);

1998 1999
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2000

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

2003
    virDomainObjEndAPI(&privdom);
2004 2005

    return 0;
2006 2007
}

2008 2009
#define TEST_SAVE_MAGIC "TestGuestMagic"

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

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

2029

2030
    if (!(privdom = testDomObjFromDomain(domain)))
2031
        goto cleanup;
2032

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

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

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

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

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

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

2088 2089
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
2090

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

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

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

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

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

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

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

2198
    event = virDomainEventLifecycleNewFromObj(dom,
2199 2200
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
2201
    ret = 0;
2202

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

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

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

E
Eric Blake 已提交
2231 2232
    virCheckFlags(VIR_DUMP_CRASH, -1);

2233

2234
    if (!(privdom = testDomObjFromDomain(domain)))
2235
        goto cleanup;
2236

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

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

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

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

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

2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299

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)
{
2300 2301 2302
    char *ret;

    ignore_value(VIR_STRDUP(ret, "linux"));
2303
    return ret;
2304 2305
}

2306 2307 2308

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

2313 2314
    if (!(privdom = testDomObjFromDomain(domain)))
        return 0;
2315

2316
    ret = virDomainDefGetMemoryTotal(privdom->def);
2317

2318
    virDomainObjEndAPI(&privdom);
2319
    return ret;
2320 2321
}

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

2327 2328
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2329 2330

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

2333
    virDomainObjEndAPI(&privdom);
2334
    return 0;
2335 2336
}

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

2343 2344
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2345

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

2351
    privdom->def->mem.cur_balloon = memory;
2352 2353
    ret = 0;

2354
 cleanup:
2355
    virDomainObjEndAPI(&privdom);
2356
    return ret;
2357 2358
}

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

2366 2367
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2368 2369
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

2370 2371
    if (!(vm = testDomObjFromDomain(domain)))
        return -1;
2372

2373
    if (!(def = virDomainObjGetOneDef(vm, flags)))
2374
        goto cleanup;
2375

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

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

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

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

2403 2404
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2405 2406
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

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

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

2417 2418
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2419

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

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

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

2439 2440 2441
    if (def &&
        virDomainDefSetVcpus(def, nrCpus) < 0)
        goto cleanup;
2442

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

2454 2455
    ret = 0;

2456
 cleanup:
2457
    virDomainObjEndAPI(&privdom);
2458
    return ret;
2459 2460
}

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

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

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

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

2492
    def = privdom->def;
C
Cole Robinson 已提交
2493 2494

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

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

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

2507 2508 2509 2510 2511
    if (!(allcpumap = virBitmapNew(hostcpus)))
        goto cleanup;

    virBitmapSetAll(allcpumap);

C
Cole Robinson 已提交
2512
    /* Clamp to actual number of vcpus */
2513 2514
    if (maxinfo > virDomainDefGetVcpus(privdom->def))
        maxinfo = virDomainDefGetVcpus(privdom->def);
C
Cole Robinson 已提交
2515

2516 2517
    memset(info, 0, sizeof(*info) * maxinfo);
    memset(cpumaps, 0, maxinfo * maplen);
C
Cole Robinson 已提交
2518

2519
    for (i = 0; i < maxinfo; i++) {
2520
        virDomainVcpuDefPtr vcpu = virDomainDefGetVcpu(def, i);
2521
        virBitmapPtr bitmap = NULL;
C
Cole Robinson 已提交
2522

2523 2524
        if (!vcpu->online)
            continue;
C
Cole Robinson 已提交
2525

2526 2527
        if (vcpu->cpumask)
            bitmap = vcpu->cpumask;
2528 2529 2530 2531
        else if (def->cpumask)
            bitmap = def->cpumask;
        else
            bitmap = allcpumap;
C
Cole Robinson 已提交
2532

2533 2534
        if (cpumaps)
            virBitmapToDataBuf(bitmap, VIR_GET_CPUMAP(cpumaps, maplen, i), maplen);
C
Cole Robinson 已提交
2535

2536 2537 2538
        info[i].number = i;
        info[i].state = VIR_VCPU_RUNNING;
        info[i].cpu = virBitmapLastSetBit(bitmap);
C
Cole Robinson 已提交
2539

2540 2541
        /* Fake an increasing cpu time value */
        info[i].cpuTime = statbase / 10;
C
Cole Robinson 已提交
2542 2543 2544
    }

    ret = maxinfo;
2545
 cleanup:
2546
    virBitmapFree(allcpumap);
2547
    virDomainObjEndAPI(&privdom);
C
Cole Robinson 已提交
2548 2549 2550
    return ret;
}

C
Cole Robinson 已提交
2551 2552 2553 2554 2555
static int testDomainPinVcpu(virDomainPtr domain,
                             unsigned int vcpu,
                             unsigned char *cpumap,
                             int maplen)
{
2556
    virDomainVcpuDefPtr vcpuinfo;
C
Cole Robinson 已提交
2557
    virDomainObjPtr privdom;
2558
    virDomainDefPtr def;
C
Cole Robinson 已提交
2559 2560
    int ret = -1;

2561 2562
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
C
Cole Robinson 已提交
2563

2564 2565
    def = privdom->def;

C
Cole Robinson 已提交
2566
    if (!virDomainObjIsActive(privdom)) {
2567
        virReportError(VIR_ERR_OPERATION_INVALID,
2568
                       "%s", _("cannot pin vcpus on an inactive domain"));
C
Cole Robinson 已提交
2569 2570 2571
        goto cleanup;
    }

2572 2573
    if (!(vcpuinfo = virDomainDefGetVcpu(def, vcpu)) ||
        !vcpuinfo->online) {
2574 2575 2576
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested vcpu '%d' is not present in the domain"),
                       vcpu);
C
Cole Robinson 已提交
2577 2578 2579
        goto cleanup;
    }

2580 2581 2582
    virBitmapFree(vcpuinfo->cpumask);

    if (!(vcpuinfo->cpumask = virBitmapNewData(cpumap, maplen)))
2583
        goto cleanup;
C
Cole Robinson 已提交
2584 2585

    ret = 0;
2586

2587
 cleanup:
2588
    virDomainObjEndAPI(&privdom);
C
Cole Robinson 已提交
2589 2590 2591
    return ret;
}

2592 2593 2594 2595 2596 2597 2598
static int
testDomainGetVcpuPinInfo(virDomainPtr dom,
                        int ncpumaps,
                        unsigned char *cpumaps,
                        int maplen,
                        unsigned int flags)
{
2599
    testDriverPtr driver = dom->conn->privateData;
2600 2601
    virDomainObjPtr privdom;
    virDomainDefPtr def;
2602
    int ret = -1;
2603 2604 2605 2606 2607 2608 2609

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

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

2610 2611 2612
    ret = virDomainDefGetVcpuPinInfoHelper(def, maplen, ncpumaps, cpumaps,
                                           VIR_NODEINFO_MAXCPUS(driver->nodeInfo),
                                           NULL);
2613 2614 2615 2616 2617 2618

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

2619
static char *testDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
2620
{
2621
    testDriverPtr privconn = domain->conn->privateData;
2622
    virDomainDefPtr def;
2623
    virDomainObjPtr privdom;
2624 2625
    char *ret = NULL;

2626 2627
    /* Flags checked by virDomainDefFormat */

2628 2629
    if (!(privdom = testDomObjFromDomain(domain)))
        return NULL;
2630

2631 2632
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
2633

2634 2635
    ret = virDomainDefFormat(def, privconn->caps,
                             virDomainDefFormatConvertXMLFlags(flags));
2636

2637
    virDomainObjEndAPI(&privdom);
2638
    return ret;
2639
}
2640

2641 2642
static int testConnectNumOfDefinedDomains(virConnectPtr conn)
{
2643
    testDriverPtr privconn = conn->privateData;
2644

2645
    return virDomainObjListNumOfDomains(privconn->domains, false, NULL, NULL);
2646 2647
}

2648 2649
static int testConnectListDefinedDomains(virConnectPtr conn,
                                         char **const names,
2650 2651
                                         int maxnames)
{
2652

2653
    testDriverPtr privconn = conn->privateData;
2654 2655

    memset(names, 0, sizeof(*names)*maxnames);
2656 2657
    return virDomainObjListGetInactiveNames(privconn->domains, names, maxnames,
                                            NULL, NULL);
2658 2659
}

2660 2661 2662
static virDomainPtr testDomainDefineXMLFlags(virConnectPtr conn,
                                             const char *xml,
                                             unsigned int flags)
2663
{
2664
    testDriverPtr privconn = conn->privateData;
2665
    virDomainPtr ret = NULL;
2666
    virDomainDefPtr def;
2667
    virDomainObjPtr dom = NULL;
2668
    virObjectEventPtr event = NULL;
2669
    virDomainDefPtr oldDef = NULL;
2670 2671 2672
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;

    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
2673

2674
    if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
2675
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
2676

2677
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
2678
                                       NULL, parse_flags)) == NULL)
2679
        goto cleanup;
2680

2681 2682 2683
    if (virXMLCheckIllegalChars("name", def->name, "\n") < 0)
        goto cleanup;

2684
    if (testDomainGenerateIfnames(def) < 0)
2685
        goto cleanup;
2686
    if (!(dom = virDomainObjListAdd(privconn->domains,
2687
                                    def,
2688
                                    privconn->xmlopt,
2689 2690
                                    0,
                                    &oldDef)))
2691
        goto cleanup;
2692
    def = NULL;
2693
    dom->persistent = 1;
2694

2695
    event = virDomainEventLifecycleNewFromObj(dom,
2696
                                     VIR_DOMAIN_EVENT_DEFINED,
2697
                                     !oldDef ?
2698 2699
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
2700

2701
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
2702
    if (ret)
2703
        ret->id = dom->def->id;
2704

2705
 cleanup:
2706
    virDomainDefFree(def);
2707
    virDomainDefFree(oldDef);
2708
    if (dom)
2709
        virObjectUnlock(dom);
2710
    testObjectEventQueue(privconn, event);
2711
    return ret;
2712 2713
}

2714 2715 2716 2717 2718 2719
static virDomainPtr
testDomainDefineXML(virConnectPtr conn, const char *xml)
{
    return testDomainDefineXMLFlags(conn, xml, 0);
}

2720 2721 2722 2723 2724 2725
static char *testDomainGetMetadata(virDomainPtr dom,
                                   int type,
                                   const char *uri,
                                   unsigned int flags)
{
    virDomainObjPtr privdom;
2726
    char *ret;
2727 2728 2729 2730

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, NULL);

2731 2732
    if (!(privdom = testDomObjFromDomain(dom)))
        return NULL;
2733

2734
    ret = virDomainObjGetMetadata(privdom, type, uri, flags);
2735

2736
    virDomainObjEndAPI(&privdom);
2737 2738 2739 2740 2741 2742 2743 2744 2745 2746
    return ret;
}

static int testDomainSetMetadata(virDomainPtr dom,
                                 int type,
                                 const char *metadata,
                                 const char *key,
                                 const char *uri,
                                 unsigned int flags)
{
2747
    testDriverPtr privconn = dom->conn->privateData;
2748
    virDomainObjPtr privdom;
2749
    int ret;
2750 2751 2752 2753

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

2754 2755
    if (!(privdom = testDomObjFromDomain(dom)))
        return -1;
2756 2757 2758

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

2761 2762 2763 2764 2765 2766
    if (ret == 0) {
        virObjectEventPtr ev = NULL;
        ev = virDomainEventMetadataChangeNewFromObj(privdom, type, uri);
        testObjectEventQueue(privconn, ev);
    }

2767
    virDomainObjEndAPI(&privdom);
2768 2769 2770 2771
    return ret;
}


2772 2773
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
2774 2775
                                      int startCell, int maxCells)
{
2776
    testDriverPtr privconn = conn->privateData;
2777 2778
    int cell;
    size_t i;
2779
    int ret = -1;
2780

2781
    testDriverLock(privconn);
2782
    if (startCell >= privconn->numCells) {
2783 2784
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("Range exceeds available cells"));
2785
        goto cleanup;
2786 2787
    }

2788 2789 2790 2791
    for (cell = startCell, i = 0;
         (cell < privconn->numCells && i < maxCells);
         ++cell, ++i) {
        freemems[i] = privconn->cells[cell].mem;
2792
    }
2793
    ret = i;
2794

2795
 cleanup:
2796
    testDriverUnlock(privconn);
2797
    return ret;
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 2838 2839 2840 2841 2842 2843 2844 2845
#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;
}
2846

2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862
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;
}

2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886
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;
}

2887 2888
static int testDomainCreateWithFlags(virDomainPtr domain, unsigned int flags)
{
2889
    testDriverPtr privconn = domain->conn->privateData;
2890
    virDomainObjPtr privdom;
2891
    virObjectEventPtr event = NULL;
2892
    int ret = -1;
2893

2894 2895
    virCheckFlags(0, -1);

2896
    testDriverLock(privconn);
2897

2898
    if (!(privdom = testDomObjFromDomain(domain)))
2899
        goto cleanup;
2900

J
Jiri Denemark 已提交
2901
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_SHUTOFF) {
2902 2903
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Domain '%s' is already running"), domain->name);
2904
        goto cleanup;
2905 2906
    }

2907
    if (testDomainStartState(privconn, privdom,
J
Jiri Denemark 已提交
2908
                             VIR_DOMAIN_RUNNING_BOOTED) < 0)
2909 2910 2911
        goto cleanup;
    domain->id = privdom->def->id;

2912
    event = virDomainEventLifecycleNewFromObj(privdom,
2913 2914
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
2915
    ret = 0;
2916

2917
 cleanup:
2918
    virDomainObjEndAPI(&privdom);
2919
    testObjectEventQueue(privconn, event);
2920
    testDriverUnlock(privconn);
2921
    return ret;
2922 2923
}

2924 2925
static int testDomainCreate(virDomainPtr domain)
{
2926 2927 2928
    return testDomainCreateWithFlags(domain, 0);
}

2929 2930 2931
static int testDomainUndefineFlags(virDomainPtr domain,
                                   unsigned int flags)
{
2932
    testDriverPtr privconn = domain->conn->privateData;
2933
    virDomainObjPtr privdom;
2934
    virObjectEventPtr event = NULL;
2935
    int nsnapshots;
2936
    int ret = -1;
2937

2938 2939
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
                  VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
2940

2941

2942
    if (!(privdom = testDomObjFromDomain(domain)))
2943
        goto cleanup;
2944

C
Cole Robinson 已提交
2945 2946 2947 2948 2949 2950 2951 2952
    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;
    }

2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970
    /* 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. */
    }

2971
    event = virDomainEventLifecycleNewFromObj(privdom,
2972 2973
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
C
Cole Robinson 已提交
2974 2975
    privdom->hasManagedSave = false;

2976
    if (virDomainObjIsActive(privdom))
2977
        privdom->persistent = 0;
2978 2979
    else
        virDomainObjListRemove(privconn->domains, privdom);
2980

2981
    ret = 0;
2982

2983
 cleanup:
2984
    virDomainObjEndAPI(&privdom);
2985
    testObjectEventQueue(privconn, event);
2986
    return ret;
2987 2988
}

2989 2990 2991 2992 2993
static int testDomainUndefine(virDomainPtr domain)
{
    return testDomainUndefineFlags(domain, 0);
}

2994 2995 2996
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
2997 2998
    virDomainObjPtr privdom;

2999 3000
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3001

3002
    *autostart = privdom->autostart;
3003

3004
    virDomainObjEndAPI(&privdom);
3005
    return 0;
3006 3007 3008 3009 3010 3011
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
3012 3013
    virDomainObjPtr privdom;

3014 3015
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3016

3017
    privdom->autostart = autostart ? 1 : 0;
3018

3019
    virDomainObjEndAPI(&privdom);
3020
    return 0;
3021
}
3022

3023
static char *testDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED,
3024 3025
                                        int *nparams)
{
3026 3027
    char *type = NULL;

3028 3029 3030
    if (nparams)
        *nparams = 1;

3031
    ignore_value(VIR_STRDUP(type, "fair"));
3032

3033 3034 3035
    return type;
}

3036
static int
3037 3038 3039 3040
testDomainGetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int *nparams,
                                      unsigned int flags)
3041
{
3042
    virDomainObjPtr privdom;
3043
    int ret = -1;
3044

3045 3046
    virCheckFlags(0, -1);

3047 3048
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3049

3050 3051
    if (virTypedParameterAssign(params, VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, 50) < 0)
3052
        goto cleanup;
3053 3054
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
3055 3056

    *nparams = 1;
3057 3058
    ret = 0;

3059
 cleanup:
3060
    virDomainObjEndAPI(&privdom);
3061
    return ret;
3062
}
3063

3064
static int
3065 3066 3067
testDomainGetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int *nparams)
3068
{
3069
    return testDomainGetSchedulerParametersFlags(domain, params, nparams, 0);
3070
}
3071

3072
static int
3073 3074 3075 3076
testDomainSetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int nparams,
                                      unsigned int flags)
3077
{
3078
    virDomainObjPtr privdom;
3079 3080
    int ret = -1;
    size_t i;
3081

3082
    virCheckFlags(0, -1);
3083 3084 3085 3086
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
3087
        return -1;
3088

3089 3090
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3091

3092
    for (i = 0; i < nparams; i++) {
3093 3094 3095
        if (STREQ(params[i].field, VIR_DOMAIN_SCHEDULER_WEIGHT)) {
            /* XXX */
            /*privdom->weight = params[i].value.ui;*/
3096
        }
3097
    }
3098

3099 3100
    ret = 0;

3101
    virDomainObjEndAPI(&privdom);
3102
    return ret;
3103 3104
}

3105
static int
3106 3107 3108
testDomainSetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int nparams)
3109
{
3110
    return testDomainSetSchedulerParametersFlags(domain, params, nparams, 0);
3111 3112
}

3113 3114
static int testDomainBlockStats(virDomainPtr domain,
                                const char *path,
3115
                                virDomainBlockStatsPtr stats)
3116 3117 3118 3119
{
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
3120
    int ret = -1;
3121

3122 3123 3124 3125 3126 3127
    if (!*path) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("summary statistics are not supported yet"));
        return ret;
    }

3128 3129
    if (!(privdom = testDomObjFromDomain(domain)))
        return ret;
3130

3131 3132 3133 3134 3135 3136
    if (!virDomainObjIsActive(privdom)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto error;
    }

3137
    if (virDomainDiskIndexByName(privdom->def, path, false) < 0) {
3138 3139
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path: %s"), path);
3140 3141 3142 3143
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
3144
        virReportSystemError(errno,
3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157
                             "%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;
3158
 error:
3159
    virDomainObjEndAPI(&privdom);
3160 3161 3162 3163 3164
    return ret;
}

static int testDomainInterfaceStats(virDomainPtr domain,
                                    const char *path,
3165
                                    virDomainInterfaceStatsPtr stats)
3166 3167 3168 3169
{
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
3170 3171
    size_t i;
    int found = 0, ret = -1;
3172

3173 3174
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3175

3176 3177 3178 3179 3180 3181
    if (!virDomainObjIsActive(privdom)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto error;
    }

3182
    for (i = 0; i < privdom->def->nnets; i++) {
3183
        if (privdom->def->nets[i]->ifname &&
3184
            STREQ(privdom->def->nets[i]->ifname, path)) {
3185 3186 3187 3188 3189 3190
            found = 1;
            break;
        }
    }

    if (!found) {
3191 3192
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path, '%s' is not a known interface"), path);
3193 3194 3195 3196
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
3197
        virReportSystemError(errno,
3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213
                             "%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;
3214
 error:
3215
    virDomainObjEndAPI(&privdom);
3216 3217 3218
    return ret;
}

3219

3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237
static virNetworkObjPtr
testNetworkObjFindByUUID(testDriverPtr privconn,
                         const unsigned char *uuid)
{
    virNetworkObjPtr net;
    char uuidstr[VIR_UUID_STRING_BUFLEN];

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

    return net;
}


3238 3239
static virNetworkPtr testNetworkLookupByUUID(virConnectPtr conn,
                                             const unsigned char *uuid)
3240
{
3241
    testDriverPtr privconn = conn->privateData;
3242
    virNetworkObjPtr net;
3243
    virNetworkPtr ret = NULL;
3244

3245
    if (!(net = testNetworkObjFindByUUID(privconn, uuid)))
3246
        goto cleanup;
3247

3248 3249
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

3250
 cleanup:
3251
    virNetworkObjEndAPI(&net);
3252
    return ret;
3253
}
3254

3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270

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

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

    return net;
}


3271
static virNetworkPtr testNetworkLookupByName(virConnectPtr conn,
3272
                                             const char *name)
3273
{
3274
    testDriverPtr privconn = conn->privateData;
3275 3276
    virNetworkObjPtr net;
    virNetworkPtr ret = NULL;
3277

3278
    if (!(net = testNetworkObjFindByName(privconn, name)))
3279
        goto cleanup;
3280

3281 3282
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

3283
 cleanup:
3284
    virNetworkObjEndAPI(&net);
3285
    return ret;
3286 3287 3288
}


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

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

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

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

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

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

3318
static int testConnectListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
3319
    testDriverPtr privconn = conn->privateData;
3320
    int n;
3321

3322 3323
    n = virNetworkObjListGetNames(privconn->networks,
                                  false, names, nnames, NULL, conn);
3324
    return n;
3325 3326
}

3327
static int
3328
testConnectListAllNetworks(virConnectPtr conn,
3329 3330 3331
                           virNetworkPtr **nets,
                           unsigned int flags)
{
3332
    testDriverPtr privconn = conn->privateData;
3333 3334 3335

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

3336
    return virNetworkObjListExport(conn, privconn->networks, nets, NULL, flags);
3337
}
3338 3339 3340

static int testNetworkIsActive(virNetworkPtr net)
{
3341
    testDriverPtr privconn = net->conn->privateData;
3342 3343 3344
    virNetworkObjPtr obj;
    int ret = -1;

3345
    if (!(obj = testNetworkObjFindByUUID(privconn, net->uuid)))
3346
        goto cleanup;
3347

3348 3349
    ret = virNetworkObjIsActive(obj);

3350
 cleanup:
3351
    virNetworkObjEndAPI(&obj);
3352 3353 3354 3355 3356
    return ret;
}

static int testNetworkIsPersistent(virNetworkPtr net)
{
3357
    testDriverPtr privconn = net->conn->privateData;
3358 3359 3360
    virNetworkObjPtr obj;
    int ret = -1;

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

3364 3365
    ret = obj->persistent;

3366
 cleanup:
3367
    virNetworkObjEndAPI(&obj);
3368 3369 3370 3371
    return ret;
}


3372 3373
static virNetworkPtr testNetworkCreateXML(virConnectPtr conn, const char *xml)
{
3374
    testDriverPtr privconn = conn->privateData;
3375
    virNetworkDefPtr def;
3376
    virNetworkObjPtr net = NULL;
3377
    virNetworkPtr ret = NULL;
3378
    virObjectEventPtr event = NULL;
3379

3380
    if ((def = virNetworkDefParseString(xml)) == NULL)
3381
        goto cleanup;
3382

3383 3384 3385
    if (!(net = virNetworkAssignDef(privconn->networks, def,
                                    VIR_NETWORK_OBJ_LIST_ADD_LIVE |
                                    VIR_NETWORK_OBJ_LIST_ADD_CHECK_LIVE)))
3386 3387
        goto cleanup;
    def = NULL;
3388
    net->active = 1;
3389

3390
    event = virNetworkEventLifecycleNew(net->def->name, net->def->uuid,
3391 3392
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3393

3394
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3395

3396
 cleanup:
3397
    virNetworkDefFree(def);
3398
    testObjectEventQueue(privconn, event);
3399
    virNetworkObjEndAPI(&net);
3400
    return ret;
3401 3402
}

3403
static
3404
virNetworkPtr testNetworkDefineXML(virConnectPtr conn, const char *xml)
3405
{
3406
    testDriverPtr privconn = conn->privateData;
3407
    virNetworkDefPtr def;
3408
    virNetworkObjPtr net = NULL;
3409
    virNetworkPtr ret = NULL;
3410
    virObjectEventPtr event = NULL;
3411

3412
    if ((def = virNetworkDefParseString(xml)) == NULL)
3413
        goto cleanup;
3414

3415
    if (!(net = virNetworkAssignDef(privconn->networks, def, 0)))
3416 3417
        goto cleanup;
    def = NULL;
3418

3419
    event = virNetworkEventLifecycleNew(net->def->name, net->def->uuid,
3420 3421
                                        VIR_NETWORK_EVENT_DEFINED,
                                        0);
3422

3423
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3424

3425
 cleanup:
3426
    virNetworkDefFree(def);
3427
    testObjectEventQueue(privconn, event);
3428
    virNetworkObjEndAPI(&net);
3429
    return ret;
3430 3431
}

3432 3433
static int testNetworkUndefine(virNetworkPtr network)
{
3434
    testDriverPtr privconn = network->conn->privateData;
3435
    virNetworkObjPtr privnet;
3436
    int ret = -1;
3437
    virObjectEventPtr event = NULL;
3438

3439
    if (!(privnet = testNetworkObjFindByName(privconn, network->name)))
3440
        goto cleanup;
3441

D
Daniel P. Berrange 已提交
3442
    if (virNetworkObjIsActive(privnet)) {
3443 3444
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is still running"), network->name);
3445
        goto cleanup;
3446 3447
    }

3448
    event = virNetworkEventLifecycleNew(network->name, network->uuid,
3449 3450
                                        VIR_NETWORK_EVENT_UNDEFINED,
                                        0);
3451

3452
    virNetworkRemoveInactive(privconn->networks, privnet);
3453
    ret = 0;
3454

3455
 cleanup:
3456
    testObjectEventQueue(privconn, event);
3457
    virNetworkObjEndAPI(&privnet);
3458
    return ret;
3459 3460
}

3461 3462 3463 3464 3465 3466 3467 3468
static int
testNetworkUpdate(virNetworkPtr net,
                  unsigned int command,
                  unsigned int section,
                  int parentIndex,
                  const char *xml,
                  unsigned int flags)
{
3469
    testDriverPtr privconn = net->conn->privateData;
3470 3471 3472 3473 3474 3475 3476
    virNetworkObjPtr network = NULL;
    int isActive, ret = -1;

    virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
                  VIR_NETWORK_UPDATE_AFFECT_CONFIG,
                  -1);

3477
    if (!(network = testNetworkObjFindByUUID(privconn, net->uuid)))
3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497
        goto cleanup;

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

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

    ret = 0;
3498
 cleanup:
3499
    virNetworkObjEndAPI(&network);
3500 3501 3502
    return ret;
}

3503 3504
static int testNetworkCreate(virNetworkPtr network)
{
3505
    testDriverPtr privconn = network->conn->privateData;
3506
    virNetworkObjPtr privnet;
3507
    int ret = -1;
3508
    virObjectEventPtr event = NULL;
3509

3510
    if (!(privnet = testNetworkObjFindByName(privconn, network->name)))
3511
        goto cleanup;
3512

D
Daniel P. Berrange 已提交
3513
    if (virNetworkObjIsActive(privnet)) {
3514 3515
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is already running"), network->name);
3516
        goto cleanup;
3517 3518
    }

3519
    privnet->active = 1;
3520
    event = virNetworkEventLifecycleNew(privnet->def->name, privnet->def->uuid,
3521 3522
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3523
    ret = 0;
3524

3525
 cleanup:
3526
    testObjectEventQueue(privconn, event);
3527
    virNetworkObjEndAPI(&privnet);
3528
    return ret;
3529 3530
}

3531 3532
static int testNetworkDestroy(virNetworkPtr network)
{
3533
    testDriverPtr privconn = network->conn->privateData;
3534
    virNetworkObjPtr privnet;
3535
    int ret = -1;
3536
    virObjectEventPtr event = NULL;
3537

3538
    if (!(privnet = testNetworkObjFindByName(privconn, network->name)))
3539
        goto cleanup;
3540

3541
    privnet->active = 0;
3542
    event = virNetworkEventLifecycleNew(privnet->def->name, privnet->def->uuid,
3543 3544
                                        VIR_NETWORK_EVENT_STOPPED,
                                        0);
3545
    if (!privnet->persistent)
3546
        virNetworkRemoveInactive(privconn->networks, privnet);
3547

3548 3549
    ret = 0;

3550
 cleanup:
3551
    testObjectEventQueue(privconn, event);
3552
    virNetworkObjEndAPI(&privnet);
3553
    return ret;
3554 3555
}

3556
static char *testNetworkGetXMLDesc(virNetworkPtr network,
E
Eric Blake 已提交
3557
                                   unsigned int flags)
3558
{
3559
    testDriverPtr privconn = network->conn->privateData;
3560
    virNetworkObjPtr privnet;
3561
    char *ret = NULL;
3562

E
Eric Blake 已提交
3563 3564
    virCheckFlags(0, NULL);

3565
    if (!(privnet = testNetworkObjFindByName(privconn, network->name)))
3566
        goto cleanup;
3567

3568
    ret = virNetworkDefFormat(privnet->def, flags);
3569

3570
 cleanup:
3571
    virNetworkObjEndAPI(&privnet);
3572
    return ret;
3573 3574 3575
}

static char *testNetworkGetBridgeName(virNetworkPtr network) {
3576
    testDriverPtr privconn = network->conn->privateData;
3577
    char *bridge = NULL;
3578 3579
    virNetworkObjPtr privnet;

3580
    if (!(privnet = testNetworkObjFindByName(privconn, network->name)))
3581
        goto cleanup;
3582

3583
    if (!(privnet->def->bridge)) {
3584 3585 3586
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("network '%s' does not have a bridge name."),
                       privnet->def->name);
3587 3588 3589
        goto cleanup;
    }

3590
    ignore_value(VIR_STRDUP(bridge, privnet->def->bridge));
3591

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

static int testNetworkGetAutostart(virNetworkPtr network,
3598 3599
                                   int *autostart)
{
3600
    testDriverPtr privconn = network->conn->privateData;
3601
    virNetworkObjPtr privnet;
3602
    int ret = -1;
3603

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

3607
    *autostart = privnet->autostart;
3608 3609
    ret = 0;

3610
 cleanup:
3611
    virNetworkObjEndAPI(&privnet);
3612
    return ret;
3613 3614 3615
}

static int testNetworkSetAutostart(virNetworkPtr network,
3616 3617
                                   int autostart)
{
3618
    testDriverPtr privconn = network->conn->privateData;
3619
    virNetworkObjPtr privnet;
3620
    int ret = -1;
3621

3622
    if (!(privnet = testNetworkObjFindByName(privconn, network->name)))
3623
        goto cleanup;
3624

3625
    privnet->autostart = autostart ? 1 : 0;
3626 3627
    ret = 0;

3628
 cleanup:
3629
    virNetworkObjEndAPI(&privnet);
3630
    return ret;
3631
}
3632

C
Cole Robinson 已提交
3633

L
Laine Stump 已提交
3634 3635 3636 3637 3638
/*
 * Physical host interface routines
 */


3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657
static virInterfaceObjPtr
testInterfaceObjFindByName(testDriverPtr privconn,
                           const char *name)
{
    virInterfaceObjPtr iface;

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

    if (!iface)
        virReportError(VIR_ERR_NO_INTERFACE,
                       _("no interface with matching name '%s'"),
                       name);

    return iface;
}


3658
static int testConnectNumOfInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3659
{
3660
    testDriverPtr privconn = conn->privateData;
3661 3662
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3663 3664

    testDriverLock(privconn);
3665
    for (i = 0; (i < privconn->ifaces.count); i++) {
L
Laine Stump 已提交
3666
        virInterfaceObjLock(privconn->ifaces.objs[i]);
3667
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i]))
L
Laine Stump 已提交
3668 3669 3670 3671 3672 3673 3674
            count++;
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3675
static int testConnectListInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3676
{
3677
    testDriverPtr privconn = conn->privateData;
3678 3679
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3680 3681 3682

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
3683
    for (i = 0; (i < privconn->ifaces.count) && (n < nnames); i++) {
L
Laine Stump 已提交
3684
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3685
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
3686
            if (VIR_STRDUP(names[n++], privconn->ifaces.objs[i]->def->name) < 0) {
L
Laine Stump 已提交
3687
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
3688
                goto error;
L
Laine Stump 已提交
3689 3690 3691 3692 3693 3694 3695 3696
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

3697
 error:
3698
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3699 3700 3701 3702 3703
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

3704
static int testConnectNumOfDefinedInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3705
{
3706
    testDriverPtr privconn = conn->privateData;
3707 3708
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3709 3710

    testDriverLock(privconn);
3711
    for (i = 0; i < privconn->ifaces.count; i++) {
L
Laine Stump 已提交
3712
        virInterfaceObjLock(privconn->ifaces.objs[i]);
3713
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i]))
L
Laine Stump 已提交
3714 3715 3716 3717 3718 3719 3720
            count++;
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3721
static int testConnectListDefinedInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3722
{
3723
    testDriverPtr privconn = conn->privateData;
3724 3725
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3726 3727 3728

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
3729
    for (i = 0; (i < privconn->ifaces.count) && (n < nnames); i++) {
L
Laine Stump 已提交
3730
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3731
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
3732
            if (VIR_STRDUP(names[n++], privconn->ifaces.objs[i]->def->name) < 0) {
L
Laine Stump 已提交
3733
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
3734
                goto error;
L
Laine Stump 已提交
3735 3736 3737 3738 3739 3740 3741 3742
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

3743
 error:
3744
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3745 3746 3747 3748 3749
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

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

3757
    if (!(iface = testInterfaceObjFindByName(privconn, name)))
L
Laine Stump 已提交
3758 3759 3760 3761
        goto cleanup;

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

3762
 cleanup:
L
Laine Stump 已提交
3763 3764 3765 3766 3767
    if (iface)
        virInterfaceObjUnlock(iface);
    return ret;
}

3768
static virInterfacePtr testInterfaceLookupByMACString(virConnectPtr conn,
L
Laine Stump 已提交
3769 3770
                                                      const char *mac)
{
3771
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3772 3773 3774 3775 3776
    virInterfaceObjPtr iface;
    int ifacect;
    virInterfacePtr ret = NULL;

    testDriverLock(privconn);
3777
    ifacect = virInterfaceObjFindByMACString(&privconn->ifaces, mac, &iface, 1);
L
Laine Stump 已提交
3778 3779 3780
    testDriverUnlock(privconn);

    if (ifacect == 0) {
3781
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3782 3783 3784 3785
        goto cleanup;
    }

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

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

3792
 cleanup:
L
Laine Stump 已提交
3793 3794 3795 3796 3797
    if (iface)
        virInterfaceObjUnlock(iface);
    return ret;
}

3798 3799
static int testInterfaceIsActive(virInterfacePtr iface)
{
3800
    testDriverPtr privconn = iface->conn->privateData;
3801 3802 3803
    virInterfaceObjPtr obj;
    int ret = -1;

3804
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
3805
        goto cleanup;
3806

3807 3808
    ret = virInterfaceObjIsActive(obj);

3809
 cleanup:
3810 3811 3812 3813 3814
    if (obj)
        virInterfaceObjUnlock(obj);
    return ret;
}

3815
static int testInterfaceChangeBegin(virConnectPtr conn,
E
Eric Blake 已提交
3816
                                    unsigned int flags)
3817
{
3818
    testDriverPtr privconn = conn->privateData;
3819 3820
    int ret = -1;

E
Eric Blake 已提交
3821 3822
    virCheckFlags(0, -1);

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

    privconn->transaction_running = true;

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

    ret = 0;
3837
 cleanup:
3838 3839 3840 3841 3842
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceChangeCommit(virConnectPtr conn,
E
Eric Blake 已提交
3843
                                     unsigned int flags)
3844
{
3845
    testDriverPtr privconn = conn->privateData;
3846 3847
    int ret = -1;

E
Eric Blake 已提交
3848 3849
    virCheckFlags(0, -1);

3850 3851 3852
    testDriverLock(privconn);

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

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

    ret = 0;

3864
 cleanup:
3865 3866 3867 3868 3869 3870
    testDriverUnlock(privconn);

    return ret;
}

static int testInterfaceChangeRollback(virConnectPtr conn,
E
Eric Blake 已提交
3871
                                       unsigned int flags)
3872
{
3873
    testDriverPtr privconn = conn->privateData;
3874 3875
    int ret = -1;

E
Eric Blake 已提交
3876 3877
    virCheckFlags(0, -1);

3878 3879 3880
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3881
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3882 3883
                       _("no transaction running, "
                         "nothing to rollback."));
3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896
        goto cleanup;
    }

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

    privconn->transaction_running = false;

    ret = 0;

3897
 cleanup:
3898 3899 3900
    testDriverUnlock(privconn);
    return ret;
}
3901

L
Laine Stump 已提交
3902
static char *testInterfaceGetXMLDesc(virInterfacePtr iface,
E
Eric Blake 已提交
3903
                                     unsigned int flags)
L
Laine Stump 已提交
3904
{
3905
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3906 3907 3908
    virInterfaceObjPtr privinterface;
    char *ret = NULL;

E
Eric Blake 已提交
3909 3910
    virCheckFlags(0, NULL);

3911
    if (!(privinterface = testInterfaceObjFindByName(privconn, iface->name)))
L
Laine Stump 已提交
3912 3913
        goto cleanup;

3914
    ret = virInterfaceDefFormat(privinterface->def);
L
Laine Stump 已提交
3915

3916
 cleanup:
L
Laine Stump 已提交
3917 3918 3919 3920 3921 3922 3923
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    return ret;
}


static virInterfacePtr testInterfaceDefineXML(virConnectPtr conn, const char *xmlStr,
E
Eric Blake 已提交
3924
                                              unsigned int flags)
L
Laine Stump 已提交
3925
{
3926
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3927 3928 3929 3930
    virInterfaceDefPtr def;
    virInterfaceObjPtr iface = NULL;
    virInterfacePtr ret = NULL;

E
Eric Blake 已提交
3931 3932
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
3933
    testDriverLock(privconn);
3934
    if ((def = virInterfaceDefParseString(xmlStr)) == NULL)
L
Laine Stump 已提交
3935 3936
        goto cleanup;

3937
    if ((iface = virInterfaceObjAssignDef(&privconn->ifaces, def)) == NULL)
L
Laine Stump 已提交
3938 3939 3940 3941 3942
        goto cleanup;
    def = NULL;

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

3943
 cleanup:
L
Laine Stump 已提交
3944 3945 3946 3947 3948 3949 3950 3951 3952
    virInterfaceDefFree(def);
    if (iface)
        virInterfaceObjUnlock(iface);
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceUndefine(virInterfacePtr iface)
{
3953
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3954 3955 3956
    virInterfaceObjPtr privinterface;
    int ret = -1;

3957
    if (!(privinterface = testInterfaceObjFindByName(privconn, iface->name)))
L
Laine Stump 已提交
3958 3959
        goto cleanup;

3960
    virInterfaceObjRemove(&privconn->ifaces, privinterface);
L
Laine Stump 已提交
3961 3962
    ret = 0;

3963
 cleanup:
L
Laine Stump 已提交
3964 3965 3966 3967 3968
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceCreate(virInterfacePtr iface,
E
Eric Blake 已提交
3969
                               unsigned int flags)
L
Laine Stump 已提交
3970
{
3971
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3972 3973 3974
    virInterfaceObjPtr privinterface;
    int ret = -1;

E
Eric Blake 已提交
3975 3976
    virCheckFlags(0, -1);

3977
    if (!(privinterface = testInterfaceObjFindByName(privconn, iface->name)))
L
Laine Stump 已提交
3978 3979 3980
        goto cleanup;

    if (privinterface->active != 0) {
3981
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
3982 3983 3984 3985 3986 3987
        goto cleanup;
    }

    privinterface->active = 1;
    ret = 0;

3988
 cleanup:
L
Laine Stump 已提交
3989 3990 3991 3992 3993 3994 3995
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceDestroy(virInterfacePtr iface,
E
Eric Blake 已提交
3996
                                unsigned int flags)
L
Laine Stump 已提交
3997
{
3998
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3999 4000 4001
    virInterfaceObjPtr privinterface;
    int ret = -1;

E
Eric Blake 已提交
4002 4003
    virCheckFlags(0, -1);

4004
    if (!(privinterface = testInterfaceObjFindByName(privconn, iface->name)))
L
Laine Stump 已提交
4005 4006 4007
        goto cleanup;

    if (privinterface->active == 0) {
4008
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
4009 4010 4011 4012 4013 4014
        goto cleanup;
    }

    privinterface->active = 0;
    ret = 0;

4015
 cleanup:
L
Laine Stump 已提交
4016 4017 4018 4019 4020 4021 4022 4023
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    testDriverUnlock(privconn);
    return ret;
}



C
Cole Robinson 已提交
4024 4025 4026 4027
/*
 * Storage Driver routines
 */

4028

4029 4030
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool)
{
C
Cole Robinson 已提交
4031 4032 4033 4034 4035

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

4036
    return VIR_STRDUP(pool->configFile, "");
C
Cole Robinson 已提交
4037 4038
}

4039

4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058
static virStoragePoolObjPtr
testStoragePoolObjFindByName(testDriverPtr privconn,
                             const char *name)
{
    virStoragePoolObjPtr pool;

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

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

    return pool;
}


4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080
static virStoragePoolObjPtr
testStoragePoolObjFindByUUID(testDriverPtr privconn,
                             const unsigned char *uuid)
{
    virStoragePoolObjPtr pool;
    char uuidstr[VIR_UUID_STRING_BUFLEN];

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

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

    return pool;
}


C
Cole Robinson 已提交
4081 4082
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
4083 4084
                            const unsigned char *uuid)
{
4085
    testDriverPtr privconn = conn->privateData;
4086 4087
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4088

4089
    if (!(pool = testStoragePoolObjFindByUUID(privconn, uuid)))
4090
        goto cleanup;
C
Cole Robinson 已提交
4091

4092 4093
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4094

4095
 cleanup:
4096 4097
    if (pool)
        virStoragePoolObjUnlock(pool);
4098
    return ret;
C
Cole Robinson 已提交
4099 4100 4101 4102
}

static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
4103 4104
                            const char *name)
{
4105
    testDriverPtr privconn = conn->privateData;
4106 4107
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4108

4109
    if (!(pool = testStoragePoolObjFindByName(privconn, name)))
4110
        goto cleanup;
C
Cole Robinson 已提交
4111

4112 4113
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4114

4115
 cleanup:
4116 4117
    if (pool)
        virStoragePoolObjUnlock(pool);
4118
    return ret;
C
Cole Robinson 已提交
4119 4120 4121
}

static virStoragePoolPtr
4122 4123
testStoragePoolLookupByVolume(virStorageVolPtr vol)
{
C
Cole Robinson 已提交
4124 4125 4126 4127
    return testStoragePoolLookupByName(vol->conn, vol->pool);
}

static int
4128 4129
testConnectNumOfStoragePools(virConnectPtr conn)
{
4130
    testDriverPtr privconn = conn->privateData;
4131 4132
    int numActive = 0;
    size_t i;
C
Cole Robinson 已提交
4133

4134
    testDriverLock(privconn);
4135
    for (i = 0; i < privconn->pools.count; i++)
C
Cole Robinson 已提交
4136 4137
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numActive++;
4138
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4139 4140 4141 4142 4143

    return numActive;
}

static int
4144 4145
testConnectListStoragePools(virConnectPtr conn,
                            char **const names,
4146 4147
                            int nnames)
{
4148
    testDriverPtr privconn = conn->privateData;
4149 4150
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
4151

4152
    testDriverLock(privconn);
C
Cole Robinson 已提交
4153
    memset(names, 0, sizeof(*names)*nnames);
4154
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
4155
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4156
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
4157
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
4158
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
4159
            goto error;
4160 4161 4162 4163
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4164 4165 4166

    return n;

4167
 error:
4168
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
4169
        VIR_FREE(names[n]);
4170
    testDriverUnlock(privconn);
4171
    return -1;
C
Cole Robinson 已提交
4172 4173 4174
}

static int
4175 4176
testConnectNumOfDefinedStoragePools(virConnectPtr conn)
{
4177
    testDriverPtr privconn = conn->privateData;
4178 4179
    int numInactive = 0;
    size_t i;
C
Cole Robinson 已提交
4180

4181
    testDriverLock(privconn);
4182
    for (i = 0; i < privconn->pools.count; i++) {
4183
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4184 4185
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numInactive++;
4186 4187 4188
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4189 4190 4191 4192 4193

    return numInactive;
}

static int
4194 4195
testConnectListDefinedStoragePools(virConnectPtr conn,
                                   char **const names,
4196 4197
                                   int nnames)
{
4198
    testDriverPtr privconn = conn->privateData;
4199 4200
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
4201

4202
    testDriverLock(privconn);
C
Cole Robinson 已提交
4203
    memset(names, 0, sizeof(*names)*nnames);
4204
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
4205
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4206
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
4207
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
4208
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
4209
            goto error;
4210 4211 4212 4213
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4214 4215 4216

    return n;

4217
 error:
4218
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
4219
        VIR_FREE(names[n]);
4220
    testDriverUnlock(privconn);
4221
    return -1;
C
Cole Robinson 已提交
4222 4223
}

4224
static int
4225 4226 4227
testConnectListAllStoragePools(virConnectPtr conn,
                               virStoragePoolPtr **pools,
                               unsigned int flags)
4228
{
4229
    testDriverPtr privconn = conn->privateData;
4230 4231 4232 4233 4234
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

    testDriverLock(privconn);
4235 4236
    ret = virStoragePoolObjListExport(conn, privconn->pools, pools,
                                      NULL, flags);
4237 4238 4239 4240
    testDriverUnlock(privconn);

    return ret;
}
C
Cole Robinson 已提交
4241

4242 4243
static int testStoragePoolIsActive(virStoragePoolPtr pool)
{
4244
    testDriverPtr privconn = pool->conn->privateData;
4245 4246 4247
    virStoragePoolObjPtr obj;
    int ret = -1;

4248
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
4249
        goto cleanup;
4250

4251 4252
    ret = virStoragePoolObjIsActive(obj);

4253
 cleanup:
4254 4255 4256 4257 4258 4259 4260
    if (obj)
        virStoragePoolObjUnlock(obj);
    return ret;
}

static int testStoragePoolIsPersistent(virStoragePoolPtr pool)
{
4261
    testDriverPtr privconn = pool->conn->privateData;
4262 4263 4264
    virStoragePoolObjPtr obj;
    int ret = -1;

4265
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
4266
        goto cleanup;
4267

4268 4269
    ret = obj->configFile ? 1 : 0;

4270
 cleanup:
4271 4272 4273 4274 4275 4276 4277
    if (obj)
        virStoragePoolObjUnlock(obj);
    return ret;
}



C
Cole Robinson 已提交
4278
static int
4279 4280
testStoragePoolCreate(virStoragePoolPtr pool,
                      unsigned int flags)
E
Eric Blake 已提交
4281
{
4282
    testDriverPtr privconn = pool->conn->privateData;
4283
    virStoragePoolObjPtr privpool;
4284
    int ret = -1;
4285
    virObjectEventPtr event = NULL;
4286

E
Eric Blake 已提交
4287 4288
    virCheckFlags(0, -1);

4289
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4290
        goto cleanup;
4291

4292
    if (virStoragePoolObjIsActive(privpool)) {
4293 4294
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4295 4296
        goto cleanup;
    }
C
Cole Robinson 已提交
4297 4298

    privpool->active = 1;
4299 4300 4301 4302

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

4305
 cleanup:
4306
    testObjectEventQueue(privconn, event);
4307 4308
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4309
    return ret;
C
Cole Robinson 已提交
4310 4311 4312
}

static char *
4313 4314 4315 4316
testConnectFindStoragePoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type,
                                  const char *srcSpec,
                                  unsigned int flags)
C
Cole Robinson 已提交
4317
{
4318 4319 4320 4321
    virStoragePoolSourcePtr source = NULL;
    int pool_type;
    char *ret = NULL;

E
Eric Blake 已提交
4322 4323
    virCheckFlags(0, NULL);

4324 4325
    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
4326 4327
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
4328 4329 4330 4331
        goto cleanup;
    }

    if (srcSpec) {
4332
        source = virStoragePoolDefParseSourceString(srcSpec, pool_type);
4333 4334 4335 4336 4337 4338 4339
        if (!source)
            goto cleanup;
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
4340
        ignore_value(VIR_STRDUP(ret, defaultPoolSourcesLogicalXML));
4341 4342 4343
        break;

    case VIR_STORAGE_POOL_NETFS:
4344
        if (!source || !source->hosts[0].name) {
4345 4346
            virReportError(VIR_ERR_INVALID_ARG,
                           "%s", _("hostname must be specified for netfs sources"));
4347 4348 4349
            goto cleanup;
        }

4350 4351
        ignore_value(virAsprintf(&ret, defaultPoolSourcesNetFSXML,
                                 source->hosts[0].name));
4352 4353 4354
        break;

    default:
4355 4356
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source discovery"), type);
4357 4358
    }

4359
 cleanup:
4360 4361
    virStoragePoolSourceFree(source);
    return ret;
C
Cole Robinson 已提交
4362 4363 4364
}


4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392
static virNodeDeviceObjPtr
testNodeDeviceMockCreateVport(testDriverPtr driver,
                              const char *wwnn,
                              const char *wwpn);
static int
testCreateVport(testDriverPtr driver,
                const char *wwnn,
                const char *wwpn)
{
    virNodeDeviceObjPtr obj = NULL;
    /* The storage_backend_scsi createVport() will use the input adapter
     * fields parent name, parent_wwnn/parent_wwpn, or parent_fabric_wwn
     * in order to determine whether the provided parent can be used to
     * create a vHBA or will find "an available vport capable" to create
     * a vHBA. In order to do this, it uses the virVHBA* API's which traverse
     * the sysfs looking at various fields (rather than going via nodedev).
     *
     * Since the test environ doesn't have the sysfs for the storage pool
     * test, at least for now use the node device test infrastructure to
     * create the vHBA. In the long run the result is the same. */
    if (!(obj = testNodeDeviceMockCreateVport(driver, wwnn, wwpn)))
        return -1;
    virNodeDeviceObjUnlock(obj);

    return 0;
}


C
Cole Robinson 已提交
4393
static virStoragePoolPtr
4394 4395 4396
testStoragePoolCreateXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4397
{
4398
    testDriverPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4399
    virStoragePoolDefPtr def;
4400
    virStoragePoolObjPtr pool = NULL;
4401
    virStoragePoolPtr ret = NULL;
4402
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
4403

E
Eric Blake 已提交
4404 4405
    virCheckFlags(0, NULL);

4406
    testDriverLock(privconn);
4407
    if (!(def = virStoragePoolDefParseString(xml)))
4408
        goto cleanup;
C
Cole Robinson 已提交
4409

4410 4411 4412 4413
    pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid);
    if (!pool)
        pool = virStoragePoolObjFindByName(&privconn->pools, def->name);
    if (pool) {
4414 4415
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("storage pool already exists"));
4416
        goto cleanup;
C
Cole Robinson 已提交
4417 4418
    }

4419
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4420
        goto cleanup;
4421
    def = NULL;
C
Cole Robinson 已提交
4422

4423
    if (pool->def->source.adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436
        /* In the real code, we'd call virVHBAManageVport followed by
         * find_new_device, but we cannot do that here since we're not
         * mocking udev. The mock routine will copy an existing vHBA and
         * rename a few fields to mock that. */
        if (testCreateVport(privconn,
                            pool->def->source.adapter.data.fchost.wwnn,
                            pool->def->source.adapter.data.fchost.wwpn) < 0) {
            virStoragePoolObjRemove(&privconn->pools, pool);
            pool = NULL;
            goto cleanup;
        }
    }

4437
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4438
        virStoragePoolObjRemove(&privconn->pools, pool);
4439 4440
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4441
    }
4442 4443 4444 4445 4446 4447

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

C
Cole Robinson 已提交
4448 4449
    pool->active = 1;

4450 4451 4452 4453
    event = virStoragePoolEventLifecycleNew(pool->def->name, pool->def->uuid,
                                            VIR_STORAGE_POOL_EVENT_STARTED,
                                            0);

4454 4455
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4456

4457
 cleanup:
4458
    virStoragePoolDefFree(def);
4459
    testObjectEventQueue(privconn, event);
4460 4461 4462
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4463
    return ret;
C
Cole Robinson 已提交
4464 4465 4466
}

static virStoragePoolPtr
4467 4468 4469
testStoragePoolDefineXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4470
{
4471
    testDriverPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4472
    virStoragePoolDefPtr def;
4473
    virStoragePoolObjPtr pool = NULL;
4474
    virStoragePoolPtr ret = NULL;
4475
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
4476

E
Eric Blake 已提交
4477 4478
    virCheckFlags(0, NULL);

4479
    testDriverLock(privconn);
4480
    if (!(def = virStoragePoolDefParseString(xml)))
4481
        goto cleanup;
C
Cole Robinson 已提交
4482 4483 4484 4485 4486

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

4487
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4488 4489
        goto cleanup;
    def = NULL;
C
Cole Robinson 已提交
4490

4491 4492 4493 4494
    event = virStoragePoolEventLifecycleNew(pool->def->name, pool->def->uuid,
                                            VIR_STORAGE_POOL_EVENT_DEFINED,
                                            0);

4495
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4496
        virStoragePoolObjRemove(&privconn->pools, pool);
4497 4498
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4499 4500
    }

4501 4502
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4503

4504
 cleanup:
4505
    virStoragePoolDefFree(def);
4506
    testObjectEventQueue(privconn, event);
4507 4508 4509
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4510
    return ret;
C
Cole Robinson 已提交
4511 4512 4513
}

static int
4514 4515
testStoragePoolUndefine(virStoragePoolPtr pool)
{
4516
    testDriverPtr privconn = pool->conn->privateData;
4517
    virStoragePoolObjPtr privpool;
4518
    int ret = -1;
4519
    virObjectEventPtr event = NULL;
4520

4521
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4522
        goto cleanup;
4523

4524
    if (virStoragePoolObjIsActive(privpool)) {
4525 4526
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4527 4528
        goto cleanup;
    }
C
Cole Robinson 已提交
4529

4530 4531 4532 4533
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_UNDEFINED,
                                            0);

C
Cole Robinson 已提交
4534
    virStoragePoolObjRemove(&privconn->pools, privpool);
4535
    privpool = NULL;
4536
    ret = 0;
C
Cole Robinson 已提交
4537

4538
 cleanup:
4539 4540
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4541
    testObjectEventQueue(privconn, event);
4542
    testDriverUnlock(privconn);
4543
    return ret;
C
Cole Robinson 已提交
4544 4545 4546
}

static int
4547
testStoragePoolBuild(virStoragePoolPtr pool,
E
Eric Blake 已提交
4548 4549
                     unsigned int flags)
{
4550
    testDriverPtr privconn = pool->conn->privateData;
4551
    virStoragePoolObjPtr privpool;
4552
    int ret = -1;
4553

E
Eric Blake 已提交
4554 4555
    virCheckFlags(0, -1);

4556
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4557
        goto cleanup;
4558

4559
    if (virStoragePoolObjIsActive(privpool)) {
4560 4561
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4562 4563
        goto cleanup;
    }
4564
    ret = 0;
C
Cole Robinson 已提交
4565

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


4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610
static int
testDestroyVport(testDriverPtr privconn,
                 const char *wwnn ATTRIBUTE_UNUSED,
                 const char *wwpn ATTRIBUTE_UNUSED)
{
    int ret = -1;
    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 */
    if (!(obj = virNodeDeviceObjFindByName(&privconn->devs, "scsi_host12"))) {
        virReportError(VIR_ERR_NO_NODE_DEVICE, "%s",
                       _("no node device with matching name 'scsi_host12'"));
        goto cleanup;
    }

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

    virNodeDeviceObjRemove(&privconn->devs, &obj);

    ret = 0;

 cleanup:
    if (obj)
        virNodeDeviceObjUnlock(obj);
    testObjectEventQueue(privconn, event);
    return ret;
}


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

4619
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4620
        goto cleanup;
4621 4622

    if (!virStoragePoolObjIsActive(privpool)) {
4623 4624
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4625
        goto cleanup;
4626
    }
C
Cole Robinson 已提交
4627 4628

    privpool->active = 0;
4629 4630

    if (privpool->def->source.adapter.type ==
4631
        VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
4632 4633 4634 4635 4636 4637 4638 4639
        if (testDestroyVport(privconn,
                             privpool->def->source.adapter.data.fchost.wwnn,
                             privpool->def->source.adapter.data.fchost.wwpn) < 0)
            goto cleanup;
    }

    event = virStoragePoolEventLifecycleNew(privpool->def->name,
                                            privpool->def->uuid,
4640 4641
                                            VIR_STORAGE_POOL_EVENT_STOPPED,
                                            0);
C
Cole Robinson 已提交
4642

4643
    if (privpool->configFile == NULL) {
C
Cole Robinson 已提交
4644
        virStoragePoolObjRemove(&privconn->pools, privpool);
4645 4646
        privpool = NULL;
    }
4647
    ret = 0;
C
Cole Robinson 已提交
4648

4649
 cleanup:
4650
    testObjectEventQueue(privconn, event);
4651 4652 4653
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
4654
    return ret;
C
Cole Robinson 已提交
4655 4656 4657 4658
}


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

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

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

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

4677
    ret = 0;
C
Cole Robinson 已提交
4678

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


static int
4687
testStoragePoolRefresh(virStoragePoolPtr pool,
E
Eric Blake 已提交
4688 4689
                       unsigned int flags)
{
4690
    testDriverPtr privconn = pool->conn->privateData;
4691
    virStoragePoolObjPtr privpool;
4692
    int ret = -1;
4693
    virObjectEventPtr event = NULL;
4694

E
Eric Blake 已提交
4695 4696
    virCheckFlags(0, -1);

4697
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4698
        goto cleanup;
4699 4700

    if (!virStoragePoolObjIsActive(privpool)) {
4701 4702
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4703
        goto cleanup;
4704
    }
4705

4706
    event = virStoragePoolEventRefreshNew(pool->name, pool->uuid);
4707
    ret = 0;
C
Cole Robinson 已提交
4708

4709
 cleanup:
4710
    testObjectEventQueue(privconn, event);
4711 4712
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4713
    return ret;
C
Cole Robinson 已提交
4714 4715 4716 4717
}


static int
4718
testStoragePoolGetInfo(virStoragePoolPtr pool,
4719 4720
                       virStoragePoolInfoPtr info)
{
4721
    testDriverPtr privconn = pool->conn->privateData;
4722
    virStoragePoolObjPtr privpool;
4723
    int ret = -1;
4724

4725
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4726
        goto cleanup;
C
Cole Robinson 已提交
4727 4728 4729 4730 4731 4732 4733 4734 4735

    memset(info, 0, sizeof(virStoragePoolInfo));
    if (privpool->active)
        info->state = VIR_STORAGE_POOL_RUNNING;
    else
        info->state = VIR_STORAGE_POOL_INACTIVE;
    info->capacity = privpool->def->capacity;
    info->allocation = privpool->def->allocation;
    info->available = privpool->def->available;
4736
    ret = 0;
C
Cole Robinson 已提交
4737

4738
 cleanup:
4739 4740
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4741
    return ret;
C
Cole Robinson 已提交
4742 4743 4744
}

static char *
4745
testStoragePoolGetXMLDesc(virStoragePoolPtr pool,
E
Eric Blake 已提交
4746 4747
                          unsigned int flags)
{
4748
    testDriverPtr privconn = pool->conn->privateData;
4749
    virStoragePoolObjPtr privpool;
4750
    char *ret = NULL;
4751

E
Eric Blake 已提交
4752 4753
    virCheckFlags(0, NULL);

4754
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4755
        goto cleanup;
4756

4757
    ret = virStoragePoolDefFormat(privpool->def);
4758

4759
 cleanup:
4760 4761
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4762
    return ret;
C
Cole Robinson 已提交
4763 4764 4765
}

static int
4766
testStoragePoolGetAutostart(virStoragePoolPtr pool,
4767 4768
                            int *autostart)
{
4769
    testDriverPtr privconn = pool->conn->privateData;
4770
    virStoragePoolObjPtr privpool;
4771
    int ret = -1;
4772

4773
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4774
        goto cleanup;
C
Cole Robinson 已提交
4775 4776 4777 4778 4779 4780

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

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

static int
4790
testStoragePoolSetAutostart(virStoragePoolPtr pool,
4791 4792
                            int autostart)
{
4793
    testDriverPtr privconn = pool->conn->privateData;
4794
    virStoragePoolObjPtr privpool;
4795
    int ret = -1;
4796

4797
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4798
        goto cleanup;
C
Cole Robinson 已提交
4799 4800

    if (!privpool->configFile) {
4801 4802
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("pool has no config file"));
4803
        goto cleanup;
C
Cole Robinson 已提交
4804 4805 4806 4807
    }

    autostart = (autostart != 0);
    privpool->autostart = autostart;
4808 4809
    ret = 0;

4810
 cleanup:
4811 4812
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4813
    return ret;
C
Cole Robinson 已提交
4814 4815 4816 4817
}


static int
4818 4819
testStoragePoolNumOfVolumes(virStoragePoolPtr pool)
{
4820
    testDriverPtr privconn = pool->conn->privateData;
4821
    virStoragePoolObjPtr privpool;
4822
    int ret = -1;
4823

4824
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4825
        goto cleanup;
4826 4827

    if (!virStoragePoolObjIsActive(privpool)) {
4828 4829
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4830
        goto cleanup;
4831
    }
C
Cole Robinson 已提交
4832

4833 4834
    ret = privpool->volumes.count;

4835
 cleanup:
4836 4837
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4838
    return ret;
C
Cole Robinson 已提交
4839 4840 4841
}

static int
4842
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4843
                           char **const names,
4844 4845
                           int maxnames)
{
4846
    testDriverPtr privconn = pool->conn->privateData;
4847
    virStoragePoolObjPtr privpool;
4848 4849
    size_t i = 0;
    int n = 0;
C
Cole Robinson 已提交
4850

4851
    memset(names, 0, maxnames * sizeof(*names));
4852

4853
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4854
        goto cleanup;
4855 4856

    if (!virStoragePoolObjIsActive(privpool)) {
4857 4858
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4859
        goto cleanup;
4860 4861
    }

4862
    for (i = 0; i < privpool->volumes.count && n < maxnames; i++) {
4863
        if (VIR_STRDUP(names[n++], privpool->volumes.objs[i]->name) < 0)
C
Cole Robinson 已提交
4864 4865 4866
            goto cleanup;
    }

4867
    virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4868 4869 4870
    return n;

 cleanup:
4871
    for (n = 0; n < maxnames; n++)
C
Cole Robinson 已提交
4872 4873
        VIR_FREE(names[i]);

4874
    memset(names, 0, maxnames * sizeof(*names));
4875 4876
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4877 4878 4879
    return -1;
}

4880 4881 4882
static int
testStoragePoolListAllVolumes(virStoragePoolPtr obj,
                              virStorageVolPtr **vols,
4883 4884
                              unsigned int flags)
{
4885
    testDriverPtr privconn = obj->conn->privateData;
4886
    virStoragePoolObjPtr pool;
4887
    size_t i;
4888 4889 4890 4891 4892 4893 4894
    virStorageVolPtr *tmp_vols = NULL;
    virStorageVolPtr vol = NULL;
    int nvols = 0;
    int ret = -1;

    virCheckFlags(0, -1);

4895
    if (!(pool = testStoragePoolObjFindByUUID(privconn, obj->uuid)))
4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909
        goto cleanup;

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

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

4910
    if (VIR_ALLOC_N(tmp_vols, pool->volumes.count + 1) < 0)
4911 4912
         goto cleanup;

4913
    for (i = 0; i < pool->volumes.count; i++) {
4914 4915
        if (!(vol = virGetStorageVol(obj->conn, pool->def->name,
                                     pool->volumes.objs[i]->name,
4916 4917
                                     pool->volumes.objs[i]->key,
                                     NULL, NULL)))
4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931
            goto cleanup;
        tmp_vols[nvols++] = vol;
    }

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

 cleanup:
    if (tmp_vols) {
        for (i = 0; i < nvols; i++) {
            if (tmp_vols[i])
                virStorageVolFree(tmp_vols[i]);
        }
4932
        VIR_FREE(tmp_vols);
4933 4934 4935 4936 4937 4938 4939
    }

    if (pool)
        virStoragePoolObjUnlock(pool);

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

static virStorageVolPtr
4942
testStorageVolLookupByName(virStoragePoolPtr pool,
4943 4944
                           const char *name ATTRIBUTE_UNUSED)
{
4945
    testDriverPtr privconn = pool->conn->privateData;
4946 4947
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
4948
    virStorageVolPtr ret = NULL;
4949

4950
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4951
        goto cleanup;
4952 4953

    if (!virStoragePoolObjIsActive(privpool)) {
4954 4955
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4956
        goto cleanup;
4957 4958 4959 4960 4961
    }

    privvol = virStorageVolDefFindByName(privpool, name);

    if (!privvol) {
4962 4963
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"), name);
4964
        goto cleanup;
C
Cole Robinson 已提交
4965 4966
    }

4967
    ret = virGetStorageVol(pool->conn, privpool->def->name,
4968 4969
                           privvol->name, privvol->key,
                           NULL, NULL);
4970

4971
 cleanup:
4972 4973
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4974
    return ret;
C
Cole Robinson 已提交
4975 4976 4977 4978
}


static virStorageVolPtr
4979
testStorageVolLookupByKey(virConnectPtr conn,
4980 4981
                          const char *key)
{
4982
    testDriverPtr privconn = conn->privateData;
4983
    size_t i;
4984
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4985

4986
    testDriverLock(privconn);
4987
    for (i = 0; i < privconn->pools.count; i++) {
4988
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4989
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4990
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4991 4992
                virStorageVolDefFindByKey(privconn->pools.objs[i], key);

4993 4994 4995 4996
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
4997 4998
                                       privvol->key,
                                       NULL, NULL);
4999
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
5000 5001
                break;
            }
C
Cole Robinson 已提交
5002
        }
5003
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
5004
    }
5005
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
5006

5007
    if (!ret)
5008 5009
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching key '%s'"), key);
5010 5011

    return ret;
C
Cole Robinson 已提交
5012 5013 5014
}

static virStorageVolPtr
5015
testStorageVolLookupByPath(virConnectPtr conn,
5016 5017
                           const char *path)
{
5018
    testDriverPtr privconn = conn->privateData;
5019
    size_t i;
5020
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
5021

5022
    testDriverLock(privconn);
5023
    for (i = 0; i < privconn->pools.count; i++) {
5024
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
5025
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
5026
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
5027 5028
                virStorageVolDefFindByPath(privconn->pools.objs[i], path);

5029 5030 5031 5032
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
5033 5034
                                       privvol->key,
                                       NULL, NULL);
5035
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
5036 5037
                break;
            }
C
Cole Robinson 已提交
5038
        }
5039
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
5040
    }
5041
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
5042

5043
    if (!ret)
5044 5045
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching path '%s'"), path);
5046 5047

    return ret;
C
Cole Robinson 已提交
5048 5049 5050
}

static virStorageVolPtr
5051 5052 5053
testStorageVolCreateXML(virStoragePoolPtr pool,
                        const char *xmldesc,
                        unsigned int flags)
E
Eric Blake 已提交
5054
{
5055
    testDriverPtr privconn = pool->conn->privateData;
5056
    virStoragePoolObjPtr privpool;
5057 5058
    virStorageVolDefPtr privvol = NULL;
    virStorageVolPtr ret = NULL;
5059

E
Eric Blake 已提交
5060 5061
    virCheckFlags(0, NULL);

5062
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
5063
        goto cleanup;
5064 5065

    if (!virStoragePoolObjIsActive(privpool)) {
5066 5067
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
5068
        goto cleanup;
5069
    }
C
Cole Robinson 已提交
5070

5071
    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
5072
    if (privvol == NULL)
5073
        goto cleanup;
5074 5075

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
5076 5077
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
5078
        goto cleanup;
C
Cole Robinson 已提交
5079 5080 5081
    }

    /* Make sure enough space */
5082
    if ((privpool->def->allocation + privvol->target.allocation) >
C
Cole Robinson 已提交
5083
         privpool->def->capacity) {
5084 5085 5086
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
5087
        goto cleanup;
C
Cole Robinson 已提交
5088 5089
    }

5090 5091
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
5092
                    privvol->name) == -1)
5093
        goto cleanup;
C
Cole Robinson 已提交
5094

5095 5096 5097
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
        VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
                                privpool->volumes.count, privvol) < 0)
5098
        goto cleanup;
C
Cole Robinson 已提交
5099

5100
    privpool->def->allocation += privvol->target.allocation;
C
Cole Robinson 已提交
5101 5102 5103
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

5104
    ret = virGetStorageVol(pool->conn, privpool->def->name,
5105 5106
                           privvol->name, privvol->key,
                           NULL, NULL);
5107
    privvol = NULL;
5108

5109
 cleanup:
5110
    virStorageVolDefFree(privvol);
5111 5112
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5113
    return ret;
C
Cole Robinson 已提交
5114 5115
}

5116
static virStorageVolPtr
5117 5118 5119 5120
testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
                            const char *xmldesc,
                            virStorageVolPtr clonevol,
                            unsigned int flags)
E
Eric Blake 已提交
5121
{
5122
    testDriverPtr privconn = pool->conn->privateData;
5123 5124 5125 5126
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol = NULL, origvol = NULL;
    virStorageVolPtr ret = NULL;

E
Eric Blake 已提交
5127 5128
    virCheckFlags(0, NULL);

5129
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
5130 5131 5132
        goto cleanup;

    if (!virStoragePoolObjIsActive(privpool)) {
5133 5134
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
5135 5136 5137
        goto cleanup;
    }

5138
    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
5139 5140 5141 5142
    if (privvol == NULL)
        goto cleanup;

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
5143 5144
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
5145 5146 5147 5148 5149
        goto cleanup;
    }

    origvol = virStorageVolDefFindByName(privpool, clonevol->name);
    if (!origvol) {
5150 5151 5152
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       clonevol->name);
5153 5154 5155 5156
        goto cleanup;
    }

    /* Make sure enough space */
5157
    if ((privpool->def->allocation + privvol->target.allocation) >
5158
         privpool->def->capacity) {
5159 5160 5161
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
5162 5163 5164 5165 5166
        goto cleanup;
    }
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

5167 5168
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
5169
                    privvol->name) == -1)
5170 5171
        goto cleanup;

5172 5173 5174
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
        VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
                                privpool->volumes.count, privvol) < 0)
5175 5176
        goto cleanup;

5177
    privpool->def->allocation += privvol->target.allocation;
5178 5179 5180 5181
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    ret = virGetStorageVol(pool->conn, privpool->def->name,
5182 5183
                           privvol->name, privvol->key,
                           NULL, NULL);
5184 5185
    privvol = NULL;

5186
 cleanup:
5187 5188 5189 5190 5191 5192
    virStorageVolDefFree(privvol);
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    return ret;
}

C
Cole Robinson 已提交
5193
static int
5194 5195
testStorageVolDelete(virStorageVolPtr vol,
                     unsigned int flags)
E
Eric Blake 已提交
5196
{
5197
    testDriverPtr privconn = vol->conn->privateData;
5198 5199
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5200
    size_t i;
5201
    int ret = -1;
C
Cole Robinson 已提交
5202

E
Eric Blake 已提交
5203 5204
    virCheckFlags(0, -1);

5205
    if (!(privpool = testStoragePoolObjFindByName(privconn, vol->pool)))
5206
        goto cleanup;
5207 5208 5209 5210

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

    if (privvol == NULL) {
5211 5212 5213
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5214
        goto cleanup;
5215 5216 5217
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5218 5219
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5220
        goto cleanup;
5221 5222 5223
    }


5224
    privpool->def->allocation -= privvol->target.allocation;
C
Cole Robinson 已提交
5225 5226 5227
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

5228
    for (i = 0; i < privpool->volumes.count; i++) {
C
Cole Robinson 已提交
5229 5230 5231
        if (privpool->volumes.objs[i] == privvol) {
            virStorageVolDefFree(privvol);

5232
            VIR_DELETE_ELEMENT(privpool->volumes.objs, i, privpool->volumes.count);
C
Cole Robinson 已提交
5233 5234 5235
            break;
        }
    }
5236
    ret = 0;
C
Cole Robinson 已提交
5237

5238
 cleanup:
5239 5240
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5241
    return ret;
C
Cole Robinson 已提交
5242 5243 5244
}


5245 5246
static int testStorageVolumeTypeForPool(int pooltype)
{
C
Cole Robinson 已提交
5247

5248
    switch (pooltype) {
C
Cole Robinson 已提交
5249 5250 5251 5252 5253 5254 5255 5256 5257 5258
        case VIR_STORAGE_POOL_DIR:
        case VIR_STORAGE_POOL_FS:
        case VIR_STORAGE_POOL_NETFS:
            return VIR_STORAGE_VOL_FILE;
        default:
            return VIR_STORAGE_VOL_BLOCK;
    }
}

static int
5259
testStorageVolGetInfo(virStorageVolPtr vol,
5260 5261
                      virStorageVolInfoPtr info)
{
5262
    testDriverPtr privconn = vol->conn->privateData;
5263 5264
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5265
    int ret = -1;
5266

5267
    if (!(privpool = testStoragePoolObjFindByName(privconn, vol->pool)))
5268
        goto cleanup;
5269 5270 5271 5272

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

    if (privvol == NULL) {
5273 5274 5275
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5276
        goto cleanup;
5277 5278 5279
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5280 5281
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5282
        goto cleanup;
5283
    }
C
Cole Robinson 已提交
5284 5285 5286

    memset(info, 0, sizeof(*info));
    info->type = testStorageVolumeTypeForPool(privpool->def->type);
5287 5288
    info->capacity = privvol->target.capacity;
    info->allocation = privvol->target.allocation;
5289
    ret = 0;
C
Cole Robinson 已提交
5290

5291
 cleanup:
5292 5293
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5294
    return ret;
C
Cole Robinson 已提交
5295 5296 5297
}

static char *
5298 5299
testStorageVolGetXMLDesc(virStorageVolPtr vol,
                         unsigned int flags)
E
Eric Blake 已提交
5300
{
5301
    testDriverPtr privconn = vol->conn->privateData;
5302 5303
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5304
    char *ret = NULL;
5305

E
Eric Blake 已提交
5306 5307
    virCheckFlags(0, NULL);

5308
    if (!(privpool = testStoragePoolObjFindByName(privconn, vol->pool)))
5309
        goto cleanup;
5310 5311 5312 5313

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

    if (privvol == NULL) {
5314 5315 5316
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5317
        goto cleanup;
5318
    }
C
Cole Robinson 已提交
5319

5320
    if (!virStoragePoolObjIsActive(privpool)) {
5321 5322
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5323
        goto cleanup;
5324 5325
    }

5326
    ret = virStorageVolDefFormat(privpool->def, privvol);
5327

5328
 cleanup:
5329 5330
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5331
    return ret;
C
Cole Robinson 已提交
5332 5333 5334
}

static char *
5335 5336
testStorageVolGetPath(virStorageVolPtr vol)
{
5337
    testDriverPtr privconn = vol->conn->privateData;
5338 5339
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5340
    char *ret = NULL;
5341

5342
    if (!(privpool = testStoragePoolObjFindByName(privconn, vol->pool)))
5343
        goto cleanup;
5344 5345 5346 5347

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

    if (privvol == NULL) {
5348 5349 5350
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5351
        goto cleanup;
5352 5353 5354
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5355 5356
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5357
        goto cleanup;
5358 5359
    }

5360
    ignore_value(VIR_STRDUP(ret, privvol->target.path));
5361

5362
 cleanup:
5363 5364
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
5365 5366 5367
    return ret;
}

5368

5369
/* Node device implementations */
5370

5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389
static virNodeDeviceObjPtr
testNodeDeviceObjFindByName(testDriverPtr driver,
                            const char *name)
{
    virNodeDeviceObjPtr obj;

    testDriverLock(driver);
    obj = virNodeDeviceObjFindByName(&driver->devs, name);
    testDriverUnlock(driver);

    if (!obj)
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       name);

    return obj;
}


5390 5391 5392
static int
testNodeNumOfDevices(virConnectPtr conn,
                     const char *cap,
E
Eric Blake 已提交
5393
                     unsigned int flags)
5394
{
5395
    testDriverPtr driver = conn->privateData;
5396
    int ndevs = 0;
5397
    size_t i;
5398

E
Eric Blake 已提交
5399 5400
    virCheckFlags(0, -1);

5401 5402 5403
    testDriverLock(driver);
    for (i = 0; i < driver->devs.count; i++)
        if ((cap == NULL) ||
5404
            virNodeDeviceObjHasCap(driver->devs.objs[i], cap))
5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415
            ++ndevs;
    testDriverUnlock(driver);

    return ndevs;
}

static int
testNodeListDevices(virConnectPtr conn,
                    const char *cap,
                    char **const names,
                    int maxnames,
E
Eric Blake 已提交
5416
                    unsigned int flags)
5417
{
5418
    testDriverPtr driver = conn->privateData;
5419
    int ndevs = 0;
5420
    size_t i;
5421

E
Eric Blake 已提交
5422 5423
    virCheckFlags(0, -1);

5424 5425 5426 5427
    testDriverLock(driver);
    for (i = 0; i < driver->devs.count && ndevs < maxnames; i++) {
        virNodeDeviceObjLock(driver->devs.objs[i]);
        if (cap == NULL ||
5428
            virNodeDeviceObjHasCap(driver->devs.objs[i], cap)) {
5429
            if (VIR_STRDUP(names[ndevs++], driver->devs.objs[i]->def->name) < 0) {
5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450
                virNodeDeviceObjUnlock(driver->devs.objs[i]);
                goto failure;
            }
        }
        virNodeDeviceObjUnlock(driver->devs.objs[i]);
    }
    testDriverUnlock(driver);

    return ndevs;

 failure:
    testDriverUnlock(driver);
    --ndevs;
    while (--ndevs >= 0)
        VIR_FREE(names[ndevs]);
    return -1;
}

static virNodeDevicePtr
testNodeDeviceLookupByName(virConnectPtr conn, const char *name)
{
5451
    testDriverPtr driver = conn->privateData;
5452 5453 5454
    virNodeDeviceObjPtr obj;
    virNodeDevicePtr ret = NULL;

5455
    if (!(obj = testNodeDeviceObjFindByName(driver, name)))
5456 5457
        goto cleanup;

5458 5459 5460 5461
    if ((ret = virGetNodeDevice(conn, name))) {
        if (VIR_STRDUP(ret->parent, obj->def->parent) < 0)
            virObjectUnref(ret);
    }
5462

5463
 cleanup:
5464 5465 5466 5467 5468 5469
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

static char *
5470
testNodeDeviceGetXMLDesc(virNodeDevicePtr dev,
E
Eric Blake 已提交
5471
                         unsigned int flags)
5472
{
5473
    testDriverPtr driver = dev->conn->privateData;
5474 5475 5476
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

E
Eric Blake 已提交
5477 5478
    virCheckFlags(0, NULL);

5479
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5480 5481
        goto cleanup;

5482
    ret = virNodeDeviceDefFormat(obj->def);
5483

5484
 cleanup:
5485 5486 5487 5488 5489 5490 5491 5492
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

static char *
testNodeDeviceGetParent(virNodeDevicePtr dev)
{
5493
    testDriverPtr driver = dev->conn->privateData;
5494 5495 5496
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

5497
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5498 5499 5500
        goto cleanup;

    if (obj->def->parent) {
5501
        ignore_value(VIR_STRDUP(ret, obj->def->parent));
5502
    } else {
5503 5504
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no parent for this device"));
5505 5506
    }

5507
 cleanup:
5508 5509 5510 5511 5512
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

5513

5514 5515 5516
static int
testNodeDeviceNumOfCaps(virNodeDevicePtr dev)
{
5517
    testDriverPtr driver = dev->conn->privateData;
5518 5519 5520 5521 5522
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

5523
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5524 5525 5526 5527 5528 5529
        goto cleanup;

    for (caps = obj->def->caps; caps; caps = caps->next)
        ++ncaps;
    ret = ncaps;

5530
 cleanup:
5531 5532 5533 5534 5535 5536 5537 5538 5539
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}


static int
testNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
5540
    testDriverPtr driver = dev->conn->privateData;
5541 5542 5543 5544 5545
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

5546
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5547 5548 5549
        goto cleanup;

    for (caps = obj->def->caps; caps && ncaps < maxnames; caps = caps->next) {
5550
        if (VIR_STRDUP(names[ncaps++], virNodeDevCapTypeToString(caps->data.type)) < 0)
5551 5552 5553 5554
            goto cleanup;
    }
    ret = ncaps;

5555
 cleanup:
5556 5557 5558 5559 5560 5561 5562 5563 5564 5565
    if (obj)
        virNodeDeviceObjUnlock(obj);
    if (ret == -1) {
        --ncaps;
        while (--ncaps >= 0)
            VIR_FREE(names[ncaps]);
    }
    return ret;
}

5566

5567 5568
static virNodeDeviceObjPtr
testNodeDeviceMockCreateVport(testDriverPtr driver,
5569
                              const char *wwnn,
5570
                              const char *wwpn)
5571
{
5572 5573
    char *xml = NULL;
    virNodeDeviceDefPtr def = NULL;
5574
    virNodeDevCapsDefPtr caps;
5575
    virNodeDeviceObjPtr obj = NULL, objcopy = NULL;
5576
    virObjectEventPtr event = NULL;
5577

5578 5579 5580 5581 5582 5583 5584 5585 5586
    /* 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. */
5587
    if (!(objcopy = virNodeDeviceObjFindByName(&driver->devs, "scsi_host11")))
5588 5589 5590 5591 5592 5593 5594 5595
        goto cleanup;

    xml = virNodeDeviceDefFormat(objcopy->def);
    virNodeDeviceObjUnlock(objcopy);
    if (!xml)
        goto cleanup;

    if (!(def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL)))
5596 5597
        goto cleanup;

5598
    VIR_FREE(def->name);
5599
    if (VIR_STRDUP(def->name, "scsi_host12") < 0)
5600 5601
        goto cleanup;

5602 5603 5604
    /* 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. */
5605 5606
    caps = def->caps;
    while (caps) {
5607
        if (caps->data.type != VIR_NODE_DEV_CAP_SCSI_HOST)
5608 5609
            continue;

5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623
        /* 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++;
        }
5624 5625 5626
        caps = caps->next;
    }

5627
    if (!(obj = virNodeDeviceObjAssignDef(&driver->devs, def)))
5628
        goto cleanup;
5629
    def = NULL;
5630

5631
    event = virNodeDeviceEventLifecycleNew(obj->def->name,
5632 5633
                                           VIR_NODE_DEVICE_EVENT_CREATED,
                                           0);
5634 5635 5636
    testObjectEventQueue(driver, event);

 cleanup:
5637
    VIR_FREE(xml);
5638 5639
    virNodeDeviceDefFree(def);
    return obj;
5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650
}


static virNodeDevicePtr
testNodeDeviceCreateXML(virConnectPtr conn,
                        const char *xmlDesc,
                        unsigned int flags)
{
    testDriverPtr driver = conn->privateData;
    virNodeDeviceDefPtr def = NULL;
    char *wwnn = NULL, *wwpn = NULL;
5651 5652
    virNodeDevicePtr dev = NULL, ret = NULL;
    virNodeDeviceObjPtr obj = NULL;
5653 5654 5655 5656 5657 5658 5659 5660

    virCheckFlags(0, NULL);

    testDriverLock(driver);

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

5661 5662 5663
    /* We run this simply for validation - it essentially validates that
     * the input XML either has a wwnn/wwpn or virNodeDevCapSCSIHostParseXML
     * generated a wwnn/wwpn */
5664 5665 5666
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) < 0)
        goto cleanup;

5667 5668 5669
    /* 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. */
5670
    if (virNodeDeviceObjGetParentHost(&driver->devs, def, CREATE_DEVICE) < 0)
5671 5672 5673 5674
        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
5675 5676 5677
     * 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 */
5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689
    if (!(obj = testNodeDeviceMockCreateVport(driver, wwnn, wwpn)))
        goto cleanup;

    if (!(dev = virGetNodeDevice(conn, obj->def->name)))
        goto cleanup;

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

    ret = dev;
    dev = NULL;
5690

5691
 cleanup:
5692 5693
    if (obj)
        virNodeDeviceObjUnlock(obj);
5694
    testDriverUnlock(driver);
5695
    virNodeDeviceDefFree(def);
5696
    virObjectUnref(dev);
5697 5698
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
5699
    return ret;
5700 5701 5702 5703 5704 5705
}

static int
testNodeDeviceDestroy(virNodeDevicePtr dev)
{
    int ret = 0;
5706
    testDriverPtr driver = dev->conn->privateData;
5707 5708
    virNodeDeviceObjPtr obj = NULL;
    char *parent_name = NULL, *wwnn = NULL, *wwpn = NULL;
5709
    virObjectEventPtr event = NULL;
5710

5711
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5712 5713
        goto out;

5714
    if (virNodeDeviceGetWWNs(obj->def, &wwnn, &wwpn) == -1)
5715 5716
        goto out;

5717
    if (VIR_STRDUP(parent_name, obj->def->parent) < 0)
5718 5719 5720 5721 5722 5723 5724 5725
        goto out;

    /* virNodeDeviceGetParentHost will cause the device object's lock to be
     * taken, so we have to dup the parent's name and drop the lock
     * before calling it.  We don't need the reference to the object
     * any more once we have the parent's name.  */
    virNodeDeviceObjUnlock(obj);

5726 5727
    /* We do this just for basic validation, but also avoid finding a
     * vport capable HBA if for some reason our vHBA doesn't exist */
5728 5729
    if (virNodeDeviceObjGetParentHost(&driver->devs, obj->def,
                                      EXISTING_DEVICE) < 0) {
5730 5731 5732 5733
        obj = NULL;
        goto out;
    }

5734 5735 5736 5737
    event = virNodeDeviceEventLifecycleNew(dev->name,
                                           VIR_NODE_DEVICE_EVENT_DELETED,
                                           0);

5738
    virNodeDeviceObjLock(obj);
5739
    virNodeDeviceObjRemove(&driver->devs, &obj);
5740

5741
 out:
5742 5743
    if (obj)
        virNodeDeviceObjUnlock(obj);
5744
    testObjectEventQueue(driver, event);
5745 5746 5747 5748 5749 5750
    VIR_FREE(parent_name);
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return ret;
}

5751 5752

/* Domain event implementations */
5753
static int
5754 5755 5756 5757
testConnectDomainEventRegister(virConnectPtr conn,
                               virConnectDomainEventCallback callback,
                               void *opaque,
                               virFreeCallback freecb)
5758
{
5759
    testDriverPtr driver = conn->privateData;
5760
    int ret = 0;
5761

5762
    if (virDomainEventStateRegister(conn, driver->eventState,
5763 5764
                                    callback, opaque, freecb) < 0)
        ret = -1;
5765 5766 5767 5768

    return ret;
}

5769

5770
static int
5771 5772
testConnectDomainEventDeregister(virConnectPtr conn,
                                 virConnectDomainEventCallback callback)
5773
{
5774
    testDriverPtr driver = conn->privateData;
5775
    int ret = 0;
5776

5777
    if (virDomainEventStateDeregister(conn, driver->eventState,
5778 5779
                                      callback) < 0)
        ret = -1;
5780 5781 5782 5783

    return ret;
}

5784 5785

static int
5786 5787 5788 5789 5790 5791
testConnectDomainEventRegisterAny(virConnectPtr conn,
                                  virDomainPtr dom,
                                  int eventID,
                                  virConnectDomainEventGenericCallback callback,
                                  void *opaque,
                                  virFreeCallback freecb)
5792
{
5793
    testDriverPtr driver = conn->privateData;
5794 5795
    int ret;

5796
    if (virDomainEventStateRegisterID(conn, driver->eventState,
5797 5798
                                      dom, eventID,
                                      callback, opaque, freecb, &ret) < 0)
5799
        ret = -1;
5800 5801 5802 5803 5804

    return ret;
}

static int
5805 5806
testConnectDomainEventDeregisterAny(virConnectPtr conn,
                                    int callbackID)
5807
{
5808
    testDriverPtr driver = conn->privateData;
5809
    int ret = 0;
5810

5811
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5812 5813
                                        callbackID) < 0)
        ret = -1;
5814 5815 5816 5817 5818

    return ret;
}


5819 5820 5821 5822 5823 5824 5825 5826
static int
testConnectNetworkEventRegisterAny(virConnectPtr conn,
                                   virNetworkPtr net,
                                   int eventID,
                                   virConnectNetworkEventGenericCallback callback,
                                   void *opaque,
                                   virFreeCallback freecb)
{
5827
    testDriverPtr driver = conn->privateData;
5828 5829
    int ret;

5830
    if (virNetworkEventStateRegisterID(conn, driver->eventState,
5831
                                       net, eventID, callback,
5832 5833 5834 5835 5836 5837 5838 5839 5840 5841
                                       opaque, freecb, &ret) < 0)
        ret = -1;

    return ret;
}

static int
testConnectNetworkEventDeregisterAny(virConnectPtr conn,
                                     int callbackID)
{
5842
    testDriverPtr driver = conn->privateData;
5843
    int ret = 0;
5844

5845
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5846 5847
                                        callbackID) < 0)
        ret = -1;
5848 5849 5850 5851

    return ret;
}

5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884
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,
                                        callbackID) < 0)
        ret = -1;

    return ret;
}

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 5911 5912 5913 5914 5915 5916 5917
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,
                                        callbackID) < 0)
        ret = -1;

    return ret;
}

5918 5919 5920
static int testConnectListAllDomains(virConnectPtr conn,
                                     virDomainPtr **domains,
                                     unsigned int flags)
5921
{
5922
    testDriverPtr privconn = conn->privateData;
5923

O
Osier Yang 已提交
5924
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
5925

5926 5927
    return virDomainObjListExport(privconn->domains, conn, domains,
                                  NULL, flags);
5928 5929
}

5930
static int
P
Peter Krempa 已提交
5931
testNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,
5932 5933 5934 5935 5936 5937 5938
                  unsigned char **cpumap,
                  unsigned int *online,
                  unsigned int flags)
{
    virCheckFlags(0, -1);

    if (cpumap) {
5939
        if (VIR_ALLOC_N(*cpumap, 1) < 0)
P
Peter Krempa 已提交
5940
            return -1;
5941 5942 5943 5944 5945 5946
        *cpumap[0] = 0x15;
    }

    if (online)
        *online = 3;

P
Peter Krempa 已提交
5947
    return  8;
5948 5949
}

5950 5951 5952 5953 5954 5955 5956 5957 5958 5959
static char *
testDomainScreenshot(virDomainPtr dom ATTRIBUTE_UNUSED,
                     virStreamPtr st,
                     unsigned int screen ATTRIBUTE_UNUSED,
                     unsigned int flags)
{
    char *ret = NULL;

    virCheckFlags(0, NULL);

5960
    if (VIR_STRDUP(ret, "image/png") < 0)
5961 5962
        return NULL;

D
Daniel P. Berrange 已提交
5963
    if (virFDStreamOpenFile(st, PKGDATADIR "/test-screenshot.png", 0, 0, O_RDONLY) < 0)
5964 5965 5966 5967 5968
        VIR_FREE(ret);

    return ret;
}

5969 5970
static int
testConnectGetCPUModelNames(virConnectPtr conn ATTRIBUTE_UNUSED,
J
Jiri Denemark 已提交
5971
                            const char *archName,
5972 5973 5974
                            char ***models,
                            unsigned int flags)
{
J
Jiri Denemark 已提交
5975 5976
    virArch arch;

5977
    virCheckFlags(0, -1);
J
Jiri Denemark 已提交
5978 5979 5980 5981 5982 5983 5984 5985

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

J
Jiri Denemark 已提交
5986
    return virCPUGetModels(arch, models);
5987
}
5988

C
Cole Robinson 已提交
5989 5990 5991
static int
testDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
5992
    testDriverPtr privconn = dom->conn->privateData;
C
Cole Robinson 已提交
5993
    virDomainObjPtr vm = NULL;
5994
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
5995 5996 5997 5998 5999 6000
    int ret = -1;

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

6001 6002
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016

    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);
6017
    event = virDomainEventLifecycleNewFromObj(vm,
C
Cole Robinson 已提交
6018 6019 6020 6021 6022
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
    vm->hasManagedSave = true;

    ret = 0;
6023
 cleanup:
6024
    virDomainObjEndAPI(&vm);
6025
    testObjectEventQueue(privconn, event);
C
Cole Robinson 已提交
6026 6027 6028 6029 6030 6031 6032 6033 6034

    return ret;
}


static int
testDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm;
6035
    int ret;
C
Cole Robinson 已提交
6036 6037 6038

    virCheckFlags(0, -1);

6039 6040
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
6041 6042

    ret = vm->hasManagedSave;
6043

6044
    virDomainObjEndAPI(&vm);
C
Cole Robinson 已提交
6045 6046 6047 6048 6049 6050 6051 6052 6053 6054
    return ret;
}

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

    virCheckFlags(0, -1);

6055 6056
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
6057 6058

    vm->hasManagedSave = false;
6059

6060
    virDomainObjEndAPI(&vm);
6061
    return 0;
C
Cole Robinson 已提交
6062 6063 6064
}


6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098
/*
 * 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;
6099
    int n;
6100 6101 6102 6103 6104

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6105
        return -1;
6106 6107 6108

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

6109
    virDomainObjEndAPI(&vm);
6110 6111 6112 6113 6114 6115 6116 6117 6118 6119
    return n;
}

static int
testDomainSnapshotListNames(virDomainPtr domain,
                            char **names,
                            int nameslen,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6120
    int n;
6121 6122 6123 6124 6125

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6126
        return -1;
6127 6128 6129 6130

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

6131
    virDomainObjEndAPI(&vm);
6132 6133 6134 6135 6136 6137 6138 6139 6140
    return n;
}

static int
testDomainListAllSnapshots(virDomainPtr domain,
                           virDomainSnapshotPtr **snaps,
                           unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6141
    int n;
6142 6143 6144 6145 6146

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6147
        return -1;
6148 6149 6150

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

6151
    virDomainObjEndAPI(&vm);
6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168
    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)))
6169
        return -1;
6170 6171 6172 6173 6174 6175 6176

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

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

6177
 cleanup:
6178
    virDomainObjEndAPI(&vm);
6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193
    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)))
6194
        return -1;
6195 6196 6197 6198 6199 6200

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

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

6201
 cleanup:
6202
    virDomainObjEndAPI(&vm);
6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218
    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)))
6219
        return -1;
6220 6221 6222 6223 6224 6225 6226

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

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

6227
 cleanup:
6228
    virDomainObjEndAPI(&vm);
6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243
    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)))
6244
        return NULL;
6245 6246 6247 6248 6249 6250

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

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

6251
 cleanup:
6252
    virDomainObjEndAPI(&vm);
6253 6254 6255 6256 6257 6258 6259 6260
    return snapshot;
}

static int
testDomainHasCurrentSnapshot(virDomainPtr domain,
                             unsigned int flags)
{
    virDomainObjPtr vm;
6261
    int ret;
6262 6263 6264 6265

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6266
        return -1;
6267 6268 6269

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

6270
    virDomainObjEndAPI(&vm);
6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284
    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)))
6285
        return NULL;
6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298

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

6299
 cleanup:
6300
    virDomainObjEndAPI(&vm);
6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313
    return parent;
}

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

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
6314
        return NULL;
6315 6316 6317 6318 6319 6320 6321 6322 6323

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

6324
 cleanup:
6325
    virDomainObjEndAPI(&vm);
6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336
    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];
6337
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6338 6339 6340 6341

    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6342
        return NULL;
6343 6344 6345 6346 6347 6348

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

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

6349
    xml = virDomainSnapshotDefFormat(uuidstr, snap->def, privconn->caps,
6350 6351
                                     virDomainDefFormatConvertXMLFlags(flags),
                                     0);
6352

6353
 cleanup:
6354
    virDomainObjEndAPI(&vm);
6355 6356 6357 6358 6359 6360 6361 6362
    return xml;
}

static int
testDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6363
    int ret;
6364 6365 6366 6367

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6368
        return -1;
6369 6370 6371 6372

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

6373
    virDomainObjEndAPI(&vm);
6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387
    return ret;
}


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

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6388
        return -1;
6389

C
Cole Robinson 已提交
6390
    if (!testSnapObjFromSnapshot(vm, snapshot))
6391 6392 6393 6394
        goto cleanup;

    ret = 1;

6395
 cleanup:
6396
    virDomainObjEndAPI(&vm);
6397 6398 6399
    return ret;
}

6400 6401 6402 6403 6404 6405
static int
testDomainSnapshotAlignDisks(virDomainObjPtr vm,
                             virDomainSnapshotDefPtr def,
                             unsigned int flags)
{
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
E
Eric Blake 已提交
6406
    bool align_match = true;
6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434

    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)
{
6435
    testDriverPtr privconn = domain->conn->privateData;
6436 6437 6438 6439
    virDomainObjPtr vm = NULL;
    virDomainSnapshotDefPtr def = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr snapshot = NULL;
6440
    virObjectEventPtr event = NULL;
6441
    char *xml = NULL;
6442 6443
    bool update_current = true;
    bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
6444 6445 6446 6447 6448 6449 6450 6451
    unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;

    /*
     * DISK_ONLY: Not implemented yet
     * REUSE_EXT: Not implemented yet
     *
     * NO_METADATA: Explicitly not implemented
     *
6452
     * REDEFINE + CURRENT: Implemented
6453 6454 6455 6456 6457 6458
     * HALT: Implemented
     * QUIESCE: Nothing to do
     * ATOMIC: Nothing to do
     * LIVE: Nothing to do
     */
    virCheckFlags(
6459 6460
        VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
        VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
6461 6462 6463 6464 6465
        VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
        VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
        VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
        VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, NULL);

6466 6467 6468 6469 6470
    if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)))
        update_current = false;
    if (redefine)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;

6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485
    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;

6486
    if (redefine) {
C
Cole Robinson 已提交
6487 6488
        if (virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
                                          &update_current, flags) < 0)
6489 6490 6491 6492 6493
            goto cleanup;
    } else {
        if (!(def->dom = virDomainDefCopy(vm->def,
                                          privconn->caps,
                                          privconn->xmlopt,
6494
                                          NULL,
6495 6496
                                          true)))
            goto cleanup;
6497

6498
        if (testDomainSnapshotAlignDisks(vm, def, flags) < 0)
6499 6500 6501
            goto cleanup;
    }

6502 6503 6504 6505
    if (!snap) {
        if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
            goto cleanup;
        def = NULL;
6506 6507
    }

6508 6509 6510 6511 6512 6513 6514 6515 6516 6517
    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);
6518
            event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
6519 6520 6521
                                    VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
        }
    }
6522 6523

    snapshot = virGetDomainSnapshot(domain, snap->def->name);
6524
 cleanup:
6525 6526 6527 6528
    VIR_FREE(xml);
    if (vm) {
        if (snapshot) {
            virDomainSnapshotObjPtr other;
6529 6530
            if (update_current)
                vm->current_snapshot = snap;
6531 6532 6533 6534 6535 6536 6537
            other = virDomainSnapshotFindByName(vm->snapshots,
                                                snap->def->parent);
            snap->parent = other;
            other->nchildren++;
            snap->sibling = other->first_child;
            other->first_child = snap;
        }
6538
        virDomainObjEndAPI(&vm);
6539
    }
6540
    testObjectEventQueue(privconn, event);
6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552
    virDomainSnapshotDefFree(def);
    return snapshot;
}


typedef struct _testSnapRemoveData testSnapRemoveData;
typedef testSnapRemoveData *testSnapRemoveDataPtr;
struct _testSnapRemoveData {
    virDomainObjPtr vm;
    bool current;
};

6553
static int
6554
testDomainSnapshotDiscardAll(void *payload,
6555 6556
                             const void *name ATTRIBUTE_UNUSED,
                             void *data)
6557 6558 6559 6560 6561 6562 6563
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapRemoveDataPtr curr = data;

    if (snap->def->current)
        curr->current = true;
    virDomainSnapshotObjListRemove(curr->vm->snapshots, snap);
6564
    return 0;
6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575
}

typedef struct _testSnapReparentData testSnapReparentData;
typedef testSnapReparentData *testSnapReparentDataPtr;
struct _testSnapReparentData {
    virDomainSnapshotObjPtr parent;
    virDomainObjPtr vm;
    int err;
    virDomainSnapshotObjPtr last;
};

6576
static int
6577 6578 6579 6580 6581 6582 6583
testDomainSnapshotReparentChildren(void *payload,
                                   const void *name ATTRIBUTE_UNUSED,
                                   void *data)
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapReparentDataPtr rep = data;

6584
    if (rep->err < 0)
6585
        return 0;
6586 6587 6588 6589 6590 6591 6592

    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;
6593
        return 0;
6594 6595 6596 6597
    }

    if (!snap->sibling)
        rep->last = snap;
6598
    return 0;
6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627
}

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) {
6628
            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)
6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671
                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;
6672
 cleanup:
6673
    virDomainObjEndAPI(&vm);
6674 6675 6676 6677 6678 6679 6680
    return ret;
}

static int
testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                           unsigned int flags)
{
6681
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6682 6683
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
6684 6685
    virObjectEventPtr event = NULL;
    virObjectEventPtr event2 = NULL;
6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748
    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;
6749 6750
    config = virDomainDefCopy(snap->def->dom, privconn->caps,
                              privconn->xmlopt, NULL, true);
6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776
    if (!config)
        goto cleanup;

    if (snap->def->state == VIR_DOMAIN_RUNNING ||
        snap->def->state == VIR_DOMAIN_PAUSED) {
        /* Transitions 2, 3, 5, 6, 8, 9 */
        bool was_running = false;
        bool was_stopped = false;

        if (virDomainObjIsActive(vm)) {
            /* Transitions 5, 6, 8, 9 */
            /* Check for ABI compatibility.  */
            if (!virDomainDefCheckABIStability(vm->def, config)) {
                virErrorPtr err = virGetLastError();

                if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_FORCE)) {
                    /* Re-spawn error using correct category. */
                    if (err->code == VIR_ERR_CONFIG_UNSUPPORTED)
                        virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY, "%s",
                                       err->str2);
                    goto cleanup;
                }

                virResetError(err);
                testDomainShutdownState(snapshot->domain, vm,
                                        VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT);
6777
                event = virDomainEventLifecycleNewFromObj(vm,
6778 6779
                            VIR_DOMAIN_EVENT_STOPPED,
                            VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
6780
                testObjectEventQueue(privconn, event);
6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791
                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. */
6792
                event = virDomainEventLifecycleNewFromObj(vm,
6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805
                                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;
6806
            event = virDomainEventLifecycleNewFromObj(vm,
6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819
                                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 */
6820
                event2 = virDomainEventLifecycleNewFromObj(vm,
6821 6822 6823 6824 6825
                                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 已提交
6826
            virObjectUnref(event);
6827 6828 6829 6830
            event = NULL;

            if (was_stopped) {
                /* Transition 2 */
6831
                event = virDomainEventLifecycleNewFromObj(vm,
6832 6833 6834 6835
                                VIR_DOMAIN_EVENT_STARTED,
                                VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            } else if (was_running) {
                /* Transition 8 */
6836
                event = virDomainEventLifecycleNewFromObj(vm,
6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848
                                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);
6849
            event = virDomainEventLifecycleNewFromObj(vm,
6850 6851 6852 6853 6854 6855 6856 6857 6858
                                    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;

6859
            testObjectEventQueue(privconn, event);
6860
            event = virDomainEventLifecycleNewFromObj(vm,
6861 6862 6863
                            VIR_DOMAIN_EVENT_STARTED,
                            VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            if (paused) {
6864
                event2 = virDomainEventLifecycleNewFromObj(vm,
6865 6866 6867 6868 6869 6870 6871 6872
                                VIR_DOMAIN_EVENT_SUSPENDED,
                                VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
            }
        }
    }

    vm->current_snapshot = snap;
    ret = 0;
6873
 cleanup:
6874
    if (event) {
6875
        testObjectEventQueue(privconn, event);
6876
        testObjectEventQueue(privconn, event2);
C
Cole Robinson 已提交
6877
    } else {
C
Cédric Bosdonnat 已提交
6878
        virObjectUnref(event2);
6879
    }
6880
    virDomainObjEndAPI(&vm);
6881 6882 6883 6884 6885

    return ret;
}


6886

6887
static virHypervisorDriver testHypervisorDriver = {
6888
    .name = "Test",
6889 6890 6891
    .connectOpen = testConnectOpen, /* 0.1.1 */
    .connectClose = testConnectClose, /* 0.1.1 */
    .connectGetVersion = testConnectGetVersion, /* 0.1.1 */
6892
    .connectGetHostname = testConnectGetHostname, /* 0.6.3 */
6893
    .connectGetMaxVcpus = testConnectGetMaxVcpus, /* 0.3.2 */
6894
    .nodeGetInfo = testNodeGetInfo, /* 0.1.1 */
6895
    .nodeGetCPUStats = testNodeGetCPUStats, /* 2.3.0 */
6896
    .nodeGetFreeMemory = testNodeGetFreeMemory, /* 2.3.0 */
6897
    .nodeGetFreePages = testNodeGetFreePages, /* 2.3.0 */
6898
    .connectGetCapabilities = testConnectGetCapabilities, /* 0.2.1 */
6899
    .connectGetSysinfo = testConnectGetSysinfo, /* 2.3.0 */
6900
    .connectGetType = testConnectGetType, /* 2.3.0 */
6901 6902 6903
    .connectListDomains = testConnectListDomains, /* 0.1.1 */
    .connectNumOfDomains = testConnectNumOfDomains, /* 0.1.1 */
    .connectListAllDomains = testConnectListAllDomains, /* 0.9.13 */
6904
    .domainCreateXML = testDomainCreateXML, /* 0.1.4 */
6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918
    .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 */
6919 6920
    .domainGetState = testDomainGetState, /* 0.9.2 */
    .domainSave = testDomainSave, /* 0.3.2 */
6921
    .domainSaveFlags = testDomainSaveFlags, /* 0.9.4 */
6922
    .domainRestore = testDomainRestore, /* 0.3.2 */
6923
    .domainRestoreFlags = testDomainRestoreFlags, /* 0.9.4 */
6924
    .domainCoreDump = testDomainCoreDump, /* 0.3.2 */
6925
    .domainCoreDumpWithFormat = testDomainCoreDumpWithFormat, /* 1.2.3 */
6926
    .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */
6927 6928 6929 6930
    .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */
    .domainGetVcpusFlags = testDomainGetVcpusFlags, /* 0.8.5 */
    .domainPinVcpu = testDomainPinVcpu, /* 0.7.3 */
    .domainGetVcpus = testDomainGetVcpus, /* 0.7.3 */
6931
    .domainGetVcpuPinInfo = testDomainGetVcpuPinInfo, /* 1.2.18 */
6932 6933
    .domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
    .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
6934 6935
    .connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
    .connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
6936 6937 6938
    .domainCreate = testDomainCreate, /* 0.1.11 */
    .domainCreateWithFlags = testDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = testDomainDefineXML, /* 0.1.11 */
6939
    .domainDefineXMLFlags = testDomainDefineXMLFlags, /* 1.2.12 */
6940
    .domainUndefine = testDomainUndefine, /* 0.1.11 */
6941
    .domainUndefineFlags = testDomainUndefineFlags, /* 0.9.4 */
6942 6943 6944
    .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
    .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
    .domainGetSchedulerType = testDomainGetSchedulerType, /* 0.3.2 */
6945 6946 6947 6948
    .domainGetSchedulerParameters = testDomainGetSchedulerParameters, /* 0.3.2 */
    .domainGetSchedulerParametersFlags = testDomainGetSchedulerParametersFlags, /* 0.9.2 */
    .domainSetSchedulerParameters = testDomainSetSchedulerParameters, /* 0.3.2 */
    .domainSetSchedulerParametersFlags = testDomainSetSchedulerParametersFlags, /* 0.9.2 */
6949 6950 6951
    .domainBlockStats = testDomainBlockStats, /* 0.7.0 */
    .domainInterfaceStats = testDomainInterfaceStats, /* 0.7.0 */
    .nodeGetCellsFreeMemory = testNodeGetCellsFreeMemory, /* 0.4.2 */
6952 6953 6954 6955
    .connectDomainEventRegister = testConnectDomainEventRegister, /* 0.6.0 */
    .connectDomainEventDeregister = testConnectDomainEventDeregister, /* 0.6.0 */
    .connectIsEncrypted = testConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = testConnectIsSecure, /* 0.7.3 */
6956 6957 6958
    .domainIsActive = testDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = testDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = testDomainIsUpdated, /* 0.8.6 */
6959 6960 6961
    .connectDomainEventRegisterAny = testConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = testConnectDomainEventDeregisterAny, /* 0.8.0 */
    .connectIsAlive = testConnectIsAlive, /* 0.9.8 */
6962
    .nodeGetCPUMap = testNodeGetCPUMap, /* 1.0.0 */
6963
    .domainScreenshot = testDomainScreenshot, /* 1.0.5 */
6964 6965
    .domainGetMetadata = testDomainGetMetadata, /* 1.1.3 */
    .domainSetMetadata = testDomainSetMetadata, /* 1.1.3 */
6966
    .connectGetCPUModelNames = testConnectGetCPUModelNames, /* 1.1.3 */
6967 6968 6969 6970 6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983
    .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 */
6984 6985 6986
    .domainSnapshotCreateXML = testDomainSnapshotCreateXML, /* 1.1.4 */
    .domainRevertToSnapshot = testDomainRevertToSnapshot, /* 1.1.4 */
    .domainSnapshotDelete = testDomainSnapshotDelete, /* 1.1.4 */
6987

E
Eric Blake 已提交
6988
    .connectBaselineCPU = testConnectBaselineCPU, /* 1.2.0 */
6989 6990 6991
};

static virNetworkDriver testNetworkDriver = {
6992 6993 6994 6995 6996
    .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 */
6997 6998
    .connectNetworkEventRegisterAny = testConnectNetworkEventRegisterAny, /* 1.2.1 */
    .connectNetworkEventDeregisterAny = testConnectNetworkEventDeregisterAny, /* 1.2.1 */
6999 7000 7001 7002
    .networkLookupByUUID = testNetworkLookupByUUID, /* 0.3.2 */
    .networkLookupByName = testNetworkLookupByName, /* 0.3.2 */
    .networkCreateXML = testNetworkCreateXML, /* 0.3.2 */
    .networkDefineXML = testNetworkDefineXML, /* 0.3.2 */
7003
    .networkUndefine = testNetworkUndefine, /* 0.3.2 */
7004
    .networkUpdate = testNetworkUpdate, /* 0.10.2 */
7005
    .networkCreate = testNetworkCreate, /* 0.3.2 */
7006 7007 7008 7009 7010 7011 7012
    .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 */
7013 7014
};

L
Laine Stump 已提交
7015
static virInterfaceDriver testInterfaceDriver = {
7016 7017 7018 7019 7020 7021
    .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 */
7022 7023 7024 7025 7026 7027
    .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 */
7028 7029 7030
    .interfaceChangeBegin = testInterfaceChangeBegin,   /* 0.9.2 */
    .interfaceChangeCommit = testInterfaceChangeCommit,  /* 0.9.2 */
    .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */
L
Laine Stump 已提交
7031 7032 7033
};


7034
static virStorageDriver testStorageDriver = {
7035 7036 7037 7038 7039 7040
    .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 */
7041 7042
    .connectStoragePoolEventRegisterAny = testConnectStoragePoolEventRegisterAny, /* 2.0.0 */
    .connectStoragePoolEventDeregisterAny = testConnectStoragePoolEventDeregisterAny, /* 2.0.0 */
7043 7044 7045
    .storagePoolLookupByName = testStoragePoolLookupByName, /* 0.5.0 */
    .storagePoolLookupByUUID = testStoragePoolLookupByUUID, /* 0.5.0 */
    .storagePoolLookupByVolume = testStoragePoolLookupByVolume, /* 0.5.0 */
7046 7047
    .storagePoolCreateXML = testStoragePoolCreateXML, /* 0.5.0 */
    .storagePoolDefineXML = testStoragePoolDefineXML, /* 0.5.0 */
7048 7049
    .storagePoolBuild = testStoragePoolBuild, /* 0.5.0 */
    .storagePoolUndefine = testStoragePoolUndefine, /* 0.5.0 */
7050
    .storagePoolCreate = testStoragePoolCreate, /* 0.5.0 */
7051 7052 7053 7054 7055 7056 7057
    .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 */
7058
    .storagePoolNumOfVolumes = testStoragePoolNumOfVolumes, /* 0.5.0 */
7059 7060 7061
    .storagePoolListVolumes = testStoragePoolListVolumes, /* 0.5.0 */
    .storagePoolListAllVolumes = testStoragePoolListAllVolumes, /* 0.10.2 */

7062 7063 7064 7065 7066 7067 7068 7069 7070
    .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 */
7071 7072
    .storagePoolIsActive = testStoragePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = testStoragePoolIsPersistent, /* 0.7.3 */
7073 7074
};

7075
static virNodeDeviceDriver testNodeDeviceDriver = {
7076 7077
    .connectNodeDeviceEventRegisterAny = testConnectNodeDeviceEventRegisterAny, /* 2.2.0 */
    .connectNodeDeviceEventDeregisterAny = testConnectNodeDeviceEventDeregisterAny, /* 2.2.0 */
7078 7079 7080 7081 7082 7083 7084 7085 7086
    .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 */
7087 7088
};

7089 7090 7091 7092 7093 7094 7095 7096
static virConnectDriver testConnectDriver = {
    .hypervisorDriver = &testHypervisorDriver,
    .interfaceDriver = &testInterfaceDriver,
    .networkDriver = &testNetworkDriver,
    .nodeDeviceDriver = &testNodeDeviceDriver,
    .nwfilterDriver = NULL,
    .secretDriver = NULL,
    .storageDriver = &testStorageDriver,
7097 7098
};

7099 7100 7101 7102 7103 7104 7105 7106
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
7107 7108
    return virRegisterConnectDriver(&testConnectDriver,
                                    false);
7109
}