test_driver.c 198.1 KB
Newer Older
1
/*
2
 * test_driver.c: A "mock" hypervisor for use by application unit tests
3
 *
4
 * Copyright (C) 2006-2015 Red Hat, Inc.
5
 * Copyright (C) 2006 Daniel P. Berrange
6
 *
7 8 9 10 11 12 13 14 15 16 17
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library.  If not, see
O
Osier Yang 已提交
19
 * <http://www.gnu.org/licenses/>.
20 21 22 23
 *
 * Daniel Berrange <berrange@redhat.com>
 */

24
#include <config.h>
25

26 27 28
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
29 30
#include <fcntl.h>
#include <unistd.h>
31
#include <sys/stat.h>
C
Cole Robinson 已提交
32
#include <libxml/xmlsave.h>
33
#include <libxml/xpathInternals.h>
34

35

36
#include "virerror.h"
37
#include "datatypes.h"
38
#include "test_driver.h"
39
#include "virbuffer.h"
40
#include "viruuid.h"
41
#include "capabilities.h"
42
#include "configmake.h"
43
#include "viralloc.h"
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
static virNetworkPtr testNetworkLookupByUUID(virConnectPtr conn,
                                             const unsigned char *uuid)
3222
{
3223
    testDriverPtr privconn = conn->privateData;
3224
    virNetworkObjPtr net;
3225
    virNetworkPtr ret = NULL;
3226

3227
    net = virNetworkObjFindByUUID(privconn->networks, uuid);
3228
    if (net == NULL) {
3229
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3230
        goto cleanup;
3231 3232
    }

3233 3234
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

3235
 cleanup:
3236
    virNetworkObjEndAPI(&net);
3237
    return ret;
3238
}
3239

3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255

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


3256
static virNetworkPtr testNetworkLookupByName(virConnectPtr conn,
3257
                                             const char *name)
3258
{
3259
    testDriverPtr privconn = conn->privateData;
3260 3261
    virNetworkObjPtr net;
    virNetworkPtr ret = NULL;
3262

3263
    if (!(net = testNetworkObjFindByName(privconn, name)))
3264
        goto cleanup;
3265

3266 3267
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

3268
 cleanup:
3269
    virNetworkObjEndAPI(&net);
3270
    return ret;
3271 3272 3273
}


3274 3275
static int testConnectNumOfNetworks(virConnectPtr conn)
{
3276
    testDriverPtr privconn = conn->privateData;
3277
    int numActive;
3278

3279 3280
    numActive = virNetworkObjListNumOfNetworks(privconn->networks,
                                               true, NULL, conn);
3281
    return numActive;
3282 3283
}

3284
static int testConnectListNetworks(virConnectPtr conn, char **const names, int nnames) {
3285
    testDriverPtr privconn = conn->privateData;
3286
    int n;
3287

3288 3289
    n = virNetworkObjListGetNames(privconn->networks,
                                  true, names, nnames, NULL, conn);
3290
    return n;
3291 3292
}

3293 3294
static int testConnectNumOfDefinedNetworks(virConnectPtr conn)
{
3295
    testDriverPtr privconn = conn->privateData;
3296
    int numInactive;
3297

3298 3299
    numInactive = virNetworkObjListNumOfNetworks(privconn->networks,
                                                 false, NULL, conn);
3300
    return numInactive;
3301 3302
}

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

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

3312
static int
3313
testConnectListAllNetworks(virConnectPtr conn,
3314 3315 3316
                           virNetworkPtr **nets,
                           unsigned int flags)
{
3317
    testDriverPtr privconn = conn->privateData;
3318 3319 3320

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

3321
    return virNetworkObjListExport(conn, privconn->networks, nets, NULL, flags);
3322
}
3323 3324 3325

static int testNetworkIsActive(virNetworkPtr net)
{
3326
    testDriverPtr privconn = net->conn->privateData;
3327 3328 3329
    virNetworkObjPtr obj;
    int ret = -1;

3330
    obj = virNetworkObjFindByUUID(privconn->networks, net->uuid);
3331
    if (!obj) {
3332
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3333 3334 3335 3336
        goto cleanup;
    }
    ret = virNetworkObjIsActive(obj);

3337
 cleanup:
3338
    virNetworkObjEndAPI(&obj);
3339 3340 3341 3342 3343
    return ret;
}

static int testNetworkIsPersistent(virNetworkPtr net)
{
3344
    testDriverPtr privconn = net->conn->privateData;
3345 3346 3347
    virNetworkObjPtr obj;
    int ret = -1;

3348
    obj = virNetworkObjFindByUUID(privconn->networks, net->uuid);
3349
    if (!obj) {
3350
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3351 3352 3353 3354
        goto cleanup;
    }
    ret = obj->persistent;

3355
 cleanup:
3356
    virNetworkObjEndAPI(&obj);
3357 3358 3359 3360
    return ret;
}


3361 3362
static virNetworkPtr testNetworkCreateXML(virConnectPtr conn, const char *xml)
{
3363
    testDriverPtr privconn = conn->privateData;
3364
    virNetworkDefPtr def;
3365
    virNetworkObjPtr net = NULL;
3366
    virNetworkPtr ret = NULL;
3367
    virObjectEventPtr event = NULL;
3368

3369
    if ((def = virNetworkDefParseString(xml)) == NULL)
3370
        goto cleanup;
3371

3372 3373 3374
    if (!(net = virNetworkAssignDef(privconn->networks, def,
                                    VIR_NETWORK_OBJ_LIST_ADD_LIVE |
                                    VIR_NETWORK_OBJ_LIST_ADD_CHECK_LIVE)))
3375 3376
        goto cleanup;
    def = NULL;
3377
    net->active = 1;
3378

3379
    event = virNetworkEventLifecycleNew(net->def->name, net->def->uuid,
3380 3381
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3382

3383
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3384

3385
 cleanup:
3386
    virNetworkDefFree(def);
3387
    testObjectEventQueue(privconn, event);
3388
    virNetworkObjEndAPI(&net);
3389
    return ret;
3390 3391
}

3392
static
3393
virNetworkPtr testNetworkDefineXML(virConnectPtr conn, const char *xml)
3394
{
3395
    testDriverPtr privconn = conn->privateData;
3396
    virNetworkDefPtr def;
3397
    virNetworkObjPtr net = NULL;
3398
    virNetworkPtr ret = NULL;
3399
    virObjectEventPtr event = NULL;
3400

3401
    if ((def = virNetworkDefParseString(xml)) == NULL)
3402
        goto cleanup;
3403

3404
    if (!(net = virNetworkAssignDef(privconn->networks, def, 0)))
3405 3406
        goto cleanup;
    def = NULL;
3407

3408
    event = virNetworkEventLifecycleNew(net->def->name, net->def->uuid,
3409 3410
                                        VIR_NETWORK_EVENT_DEFINED,
                                        0);
3411

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

3414
 cleanup:
3415
    virNetworkDefFree(def);
3416
    testObjectEventQueue(privconn, event);
3417
    virNetworkObjEndAPI(&net);
3418
    return ret;
3419 3420
}

3421 3422
static int testNetworkUndefine(virNetworkPtr network)
{
3423
    testDriverPtr privconn = network->conn->privateData;
3424
    virNetworkObjPtr privnet;
3425
    int ret = -1;
3426
    virObjectEventPtr event = NULL;
3427

3428
    if (!(privnet = testNetworkObjFindByName(privconn, network->name)))
3429
        goto cleanup;
3430

D
Daniel P. Berrange 已提交
3431
    if (virNetworkObjIsActive(privnet)) {
3432 3433
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is still running"), network->name);
3434
        goto cleanup;
3435 3436
    }

3437
    event = virNetworkEventLifecycleNew(network->name, network->uuid,
3438 3439
                                        VIR_NETWORK_EVENT_UNDEFINED,
                                        0);
3440

3441
    virNetworkRemoveInactive(privconn->networks, privnet);
3442
    ret = 0;
3443

3444
 cleanup:
3445
    testObjectEventQueue(privconn, event);
3446
    virNetworkObjEndAPI(&privnet);
3447
    return ret;
3448 3449
}

3450 3451 3452 3453 3454 3455 3456 3457
static int
testNetworkUpdate(virNetworkPtr net,
                  unsigned int command,
                  unsigned int section,
                  int parentIndex,
                  const char *xml,
                  unsigned int flags)
{
3458
    testDriverPtr privconn = net->conn->privateData;
3459 3460 3461 3462 3463 3464 3465
    virNetworkObjPtr network = NULL;
    int isActive, ret = -1;

    virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
                  VIR_NETWORK_UPDATE_AFFECT_CONFIG,
                  -1);

3466
    network = virNetworkObjFindByUUID(privconn->networks, net->uuid);
3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490
    if (!network) {
        virReportError(VIR_ERR_NO_NETWORK,
                       "%s", _("no network with matching uuid"));
        goto cleanup;
    }

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

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

    ret = 0;
3491
 cleanup:
3492
    virNetworkObjEndAPI(&network);
3493 3494 3495
    return ret;
}

3496 3497
static int testNetworkCreate(virNetworkPtr network)
{
3498
    testDriverPtr privconn = network->conn->privateData;
3499
    virNetworkObjPtr privnet;
3500
    int ret = -1;
3501
    virObjectEventPtr event = NULL;
3502

3503
    if (!(privnet = testNetworkObjFindByName(privconn, network->name)))
3504
        goto cleanup;
3505

D
Daniel P. Berrange 已提交
3506
    if (virNetworkObjIsActive(privnet)) {
3507 3508
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is already running"), network->name);
3509
        goto cleanup;
3510 3511
    }

3512
    privnet->active = 1;
3513
    event = virNetworkEventLifecycleNew(privnet->def->name, privnet->def->uuid,
3514 3515
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3516
    ret = 0;
3517

3518
 cleanup:
3519
    testObjectEventQueue(privconn, event);
3520
    virNetworkObjEndAPI(&privnet);
3521
    return ret;
3522 3523
}

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

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

3534
    privnet->active = 0;
3535
    event = virNetworkEventLifecycleNew(privnet->def->name, privnet->def->uuid,
3536 3537
                                        VIR_NETWORK_EVENT_STOPPED,
                                        0);
3538
    if (!privnet->persistent)
3539
        virNetworkRemoveInactive(privconn->networks, privnet);
3540

3541 3542
    ret = 0;

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

3549
static char *testNetworkGetXMLDesc(virNetworkPtr network,
E
Eric Blake 已提交
3550
                                   unsigned int flags)
3551
{
3552
    testDriverPtr privconn = network->conn->privateData;
3553
    virNetworkObjPtr privnet;
3554
    char *ret = NULL;
3555

E
Eric Blake 已提交
3556 3557
    virCheckFlags(0, NULL);

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

3561
    ret = virNetworkDefFormat(privnet->def, flags);
3562

3563
 cleanup:
3564
    virNetworkObjEndAPI(&privnet);
3565
    return ret;
3566 3567 3568
}

static char *testNetworkGetBridgeName(virNetworkPtr network) {
3569
    testDriverPtr privconn = network->conn->privateData;
3570
    char *bridge = NULL;
3571 3572
    virNetworkObjPtr privnet;

3573
    if (!(privnet = testNetworkObjFindByName(privconn, network->name)))
3574
        goto cleanup;
3575

3576
    if (!(privnet->def->bridge)) {
3577 3578 3579
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("network '%s' does not have a bridge name."),
                       privnet->def->name);
3580 3581 3582
        goto cleanup;
    }

3583
    ignore_value(VIR_STRDUP(bridge, privnet->def->bridge));
3584

3585
 cleanup:
3586
    virNetworkObjEndAPI(&privnet);
3587 3588 3589 3590
    return bridge;
}

static int testNetworkGetAutostart(virNetworkPtr network,
3591 3592
                                   int *autostart)
{
3593
    testDriverPtr privconn = network->conn->privateData;
3594
    virNetworkObjPtr privnet;
3595
    int ret = -1;
3596

3597
    if (!(privnet = testNetworkObjFindByName(privconn, network->name)))
3598
        goto cleanup;
3599

3600
    *autostart = privnet->autostart;
3601 3602
    ret = 0;

3603
 cleanup:
3604
    virNetworkObjEndAPI(&privnet);
3605
    return ret;
3606 3607 3608
}

static int testNetworkSetAutostart(virNetworkPtr network,
3609 3610
                                   int autostart)
{
3611
    testDriverPtr privconn = network->conn->privateData;
3612
    virNetworkObjPtr privnet;
3613
    int ret = -1;
3614

3615
    if (!(privnet = testNetworkObjFindByName(privconn, network->name)))
3616
        goto cleanup;
3617

3618
    privnet->autostart = autostart ? 1 : 0;
3619 3620
    ret = 0;

3621
 cleanup:
3622
    virNetworkObjEndAPI(&privnet);
3623
    return ret;
3624
}
3625

C
Cole Robinson 已提交
3626

L
Laine Stump 已提交
3627 3628 3629 3630 3631
/*
 * Physical host interface routines
 */


3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650
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;
}


3651
static int testConnectNumOfInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3652
{
3653
    testDriverPtr privconn = conn->privateData;
3654 3655
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3656 3657

    testDriverLock(privconn);
3658
    for (i = 0; (i < privconn->ifaces.count); i++) {
L
Laine Stump 已提交
3659
        virInterfaceObjLock(privconn->ifaces.objs[i]);
3660
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i]))
L
Laine Stump 已提交
3661 3662 3663 3664 3665 3666 3667
            count++;
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3668
static int testConnectListInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3669
{
3670
    testDriverPtr privconn = conn->privateData;
3671 3672
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3673 3674 3675

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

    return n;

3690
 error:
3691
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3692 3693 3694 3695 3696
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

3697
static int testConnectNumOfDefinedInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3698
{
3699
    testDriverPtr privconn = conn->privateData;
3700 3701
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3702 3703

    testDriverLock(privconn);
3704
    for (i = 0; i < privconn->ifaces.count; i++) {
L
Laine Stump 已提交
3705
        virInterfaceObjLock(privconn->ifaces.objs[i]);
3706
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i]))
L
Laine Stump 已提交
3707 3708 3709 3710 3711 3712 3713
            count++;
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3714
static int testConnectListDefinedInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3715
{
3716
    testDriverPtr privconn = conn->privateData;
3717 3718
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3719 3720 3721

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

    return n;

3736
 error:
3737
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3738 3739 3740 3741 3742
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

3743
static virInterfacePtr testInterfaceLookupByName(virConnectPtr conn,
L
Laine Stump 已提交
3744 3745
                                                 const char *name)
{
3746
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3747 3748 3749
    virInterfaceObjPtr iface;
    virInterfacePtr ret = NULL;

3750
    if (!(iface = testInterfaceObjFindByName(privconn, name)))
L
Laine Stump 已提交
3751 3752 3753 3754
        goto cleanup;

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

3755
 cleanup:
L
Laine Stump 已提交
3756 3757 3758 3759 3760
    if (iface)
        virInterfaceObjUnlock(iface);
    return ret;
}

3761
static virInterfacePtr testInterfaceLookupByMACString(virConnectPtr conn,
L
Laine Stump 已提交
3762 3763
                                                      const char *mac)
{
3764
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3765 3766 3767 3768 3769
    virInterfaceObjPtr iface;
    int ifacect;
    virInterfacePtr ret = NULL;

    testDriverLock(privconn);
3770
    ifacect = virInterfaceObjFindByMACString(&privconn->ifaces, mac, &iface, 1);
L
Laine Stump 已提交
3771 3772 3773
    testDriverUnlock(privconn);

    if (ifacect == 0) {
3774
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3775 3776 3777 3778
        goto cleanup;
    }

    if (ifacect > 1) {
3779
        virReportError(VIR_ERR_MULTIPLE_INTERFACES, NULL);
L
Laine Stump 已提交
3780 3781 3782 3783 3784
        goto cleanup;
    }

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

3785
 cleanup:
L
Laine Stump 已提交
3786 3787 3788 3789 3790
    if (iface)
        virInterfaceObjUnlock(iface);
    return ret;
}

3791 3792
static int testInterfaceIsActive(virInterfacePtr iface)
{
3793
    testDriverPtr privconn = iface->conn->privateData;
3794 3795 3796
    virInterfaceObjPtr obj;
    int ret = -1;

3797
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
3798
        goto cleanup;
3799

3800 3801
    ret = virInterfaceObjIsActive(obj);

3802
 cleanup:
3803 3804 3805 3806 3807
    if (obj)
        virInterfaceObjUnlock(obj);
    return ret;
}

3808
static int testInterfaceChangeBegin(virConnectPtr conn,
E
Eric Blake 已提交
3809
                                    unsigned int flags)
3810
{
3811
    testDriverPtr privconn = conn->privateData;
3812 3813
    int ret = -1;

E
Eric Blake 已提交
3814 3815
    virCheckFlags(0, -1);

3816 3817
    testDriverLock(privconn);
    if (privconn->transaction_running) {
3818
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3819
                       _("there is another transaction running."));
3820 3821 3822 3823 3824 3825 3826 3827 3828 3829
        goto cleanup;
    }

    privconn->transaction_running = true;

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

    ret = 0;
3830
 cleanup:
3831 3832 3833 3834 3835
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceChangeCommit(virConnectPtr conn,
E
Eric Blake 已提交
3836
                                     unsigned int flags)
3837
{
3838
    testDriverPtr privconn = conn->privateData;
3839 3840
    int ret = -1;

E
Eric Blake 已提交
3841 3842
    virCheckFlags(0, -1);

3843 3844 3845
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3846
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3847 3848
                       _("no transaction running, "
                         "nothing to be committed."));
3849 3850 3851 3852 3853 3854 3855 3856
        goto cleanup;
    }

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

    ret = 0;

3857
 cleanup:
3858 3859 3860 3861 3862 3863
    testDriverUnlock(privconn);

    return ret;
}

static int testInterfaceChangeRollback(virConnectPtr conn,
E
Eric Blake 已提交
3864
                                       unsigned int flags)
3865
{
3866
    testDriverPtr privconn = conn->privateData;
3867 3868
    int ret = -1;

E
Eric Blake 已提交
3869 3870
    virCheckFlags(0, -1);

3871 3872 3873
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3874
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3875 3876
                       _("no transaction running, "
                         "nothing to rollback."));
3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889
        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;

3890
 cleanup:
3891 3892 3893
    testDriverUnlock(privconn);
    return ret;
}
3894

L
Laine Stump 已提交
3895
static char *testInterfaceGetXMLDesc(virInterfacePtr iface,
E
Eric Blake 已提交
3896
                                     unsigned int flags)
L
Laine Stump 已提交
3897
{
3898
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3899 3900 3901
    virInterfaceObjPtr privinterface;
    char *ret = NULL;

E
Eric Blake 已提交
3902 3903
    virCheckFlags(0, NULL);

3904
    if (!(privinterface = testInterfaceObjFindByName(privconn, iface->name)))
L
Laine Stump 已提交
3905 3906
        goto cleanup;

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

3909
 cleanup:
L
Laine Stump 已提交
3910 3911 3912 3913 3914 3915 3916
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    return ret;
}


static virInterfacePtr testInterfaceDefineXML(virConnectPtr conn, const char *xmlStr,
E
Eric Blake 已提交
3917
                                              unsigned int flags)
L
Laine Stump 已提交
3918
{
3919
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3920 3921 3922 3923
    virInterfaceDefPtr def;
    virInterfaceObjPtr iface = NULL;
    virInterfacePtr ret = NULL;

E
Eric Blake 已提交
3924 3925
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
3926
    testDriverLock(privconn);
3927
    if ((def = virInterfaceDefParseString(xmlStr)) == NULL)
L
Laine Stump 已提交
3928 3929
        goto cleanup;

3930
    if ((iface = virInterfaceObjAssignDef(&privconn->ifaces, def)) == NULL)
L
Laine Stump 已提交
3931 3932 3933 3934 3935
        goto cleanup;
    def = NULL;

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

3936
 cleanup:
L
Laine Stump 已提交
3937 3938 3939 3940 3941 3942 3943 3944 3945
    virInterfaceDefFree(def);
    if (iface)
        virInterfaceObjUnlock(iface);
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceUndefine(virInterfacePtr iface)
{
3946
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3947 3948 3949
    virInterfaceObjPtr privinterface;
    int ret = -1;

3950
    if (!(privinterface = testInterfaceObjFindByName(privconn, iface->name)))
L
Laine Stump 已提交
3951 3952
        goto cleanup;

3953
    virInterfaceObjRemove(&privconn->ifaces, privinterface);
L
Laine Stump 已提交
3954 3955
    ret = 0;

3956
 cleanup:
L
Laine Stump 已提交
3957 3958 3959 3960 3961
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceCreate(virInterfacePtr iface,
E
Eric Blake 已提交
3962
                               unsigned int flags)
L
Laine Stump 已提交
3963
{
3964
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3965 3966 3967
    virInterfaceObjPtr privinterface;
    int ret = -1;

E
Eric Blake 已提交
3968 3969
    virCheckFlags(0, -1);

3970
    if (!(privinterface = testInterfaceObjFindByName(privconn, iface->name)))
L
Laine Stump 已提交
3971 3972 3973
        goto cleanup;

    if (privinterface->active != 0) {
3974
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
3975 3976 3977 3978 3979 3980
        goto cleanup;
    }

    privinterface->active = 1;
    ret = 0;

3981
 cleanup:
L
Laine Stump 已提交
3982 3983 3984 3985 3986 3987 3988
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceDestroy(virInterfacePtr iface,
E
Eric Blake 已提交
3989
                                unsigned int flags)
L
Laine Stump 已提交
3990
{
3991
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3992 3993 3994
    virInterfaceObjPtr privinterface;
    int ret = -1;

E
Eric Blake 已提交
3995 3996
    virCheckFlags(0, -1);

3997
    if (!(privinterface = testInterfaceObjFindByName(privconn, iface->name)))
L
Laine Stump 已提交
3998 3999 4000
        goto cleanup;

    if (privinterface->active == 0) {
4001
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
4002 4003 4004 4005 4006 4007
        goto cleanup;
    }

    privinterface->active = 0;
    ret = 0;

4008
 cleanup:
L
Laine Stump 已提交
4009 4010 4011 4012 4013 4014 4015 4016
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    testDriverUnlock(privconn);
    return ret;
}



C
Cole Robinson 已提交
4017 4018 4019 4020
/*
 * Storage Driver routines
 */

4021

4022 4023
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool)
{
C
Cole Robinson 已提交
4024 4025 4026 4027 4028

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

4029
    return VIR_STRDUP(pool->configFile, "");
C
Cole Robinson 已提交
4030 4031
}

4032

4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051
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;
}


C
Cole Robinson 已提交
4052 4053
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
4054 4055
                            const unsigned char *uuid)
{
4056
    testDriverPtr privconn = conn->privateData;
4057 4058
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4059

4060
    testDriverLock(privconn);
4061
    pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid);
4062
    testDriverUnlock(privconn);
4063 4064

    if (pool == NULL) {
4065
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4066
        goto cleanup;
C
Cole Robinson 已提交
4067 4068
    }

4069 4070
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4071

4072
 cleanup:
4073 4074
    if (pool)
        virStoragePoolObjUnlock(pool);
4075
    return ret;
C
Cole Robinson 已提交
4076 4077 4078 4079
}

static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
4080 4081
                            const char *name)
{
4082
    testDriverPtr privconn = conn->privateData;
4083 4084
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4085

4086
    if (!(pool = testStoragePoolObjFindByName(privconn, name)))
4087
        goto cleanup;
C
Cole Robinson 已提交
4088

4089 4090
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4091

4092
 cleanup:
4093 4094
    if (pool)
        virStoragePoolObjUnlock(pool);
4095
    return ret;
C
Cole Robinson 已提交
4096 4097 4098
}

static virStoragePoolPtr
4099 4100
testStoragePoolLookupByVolume(virStorageVolPtr vol)
{
C
Cole Robinson 已提交
4101 4102 4103 4104
    return testStoragePoolLookupByName(vol->conn, vol->pool);
}

static int
4105 4106
testConnectNumOfStoragePools(virConnectPtr conn)
{
4107
    testDriverPtr privconn = conn->privateData;
4108 4109
    int numActive = 0;
    size_t i;
C
Cole Robinson 已提交
4110

4111
    testDriverLock(privconn);
4112
    for (i = 0; i < privconn->pools.count; i++)
C
Cole Robinson 已提交
4113 4114
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numActive++;
4115
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4116 4117 4118 4119 4120

    return numActive;
}

static int
4121 4122
testConnectListStoragePools(virConnectPtr conn,
                            char **const names,
4123 4124
                            int nnames)
{
4125
    testDriverPtr privconn = conn->privateData;
4126 4127
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
4128

4129
    testDriverLock(privconn);
C
Cole Robinson 已提交
4130
    memset(names, 0, sizeof(*names)*nnames);
4131
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
4132
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4133
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
4134
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
4135
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
4136
            goto error;
4137 4138 4139 4140
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4141 4142 4143

    return n;

4144
 error:
4145
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
4146
        VIR_FREE(names[n]);
4147
    testDriverUnlock(privconn);
4148
    return -1;
C
Cole Robinson 已提交
4149 4150 4151
}

static int
4152 4153
testConnectNumOfDefinedStoragePools(virConnectPtr conn)
{
4154
    testDriverPtr privconn = conn->privateData;
4155 4156
    int numInactive = 0;
    size_t i;
C
Cole Robinson 已提交
4157

4158
    testDriverLock(privconn);
4159
    for (i = 0; i < privconn->pools.count; i++) {
4160
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4161 4162
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numInactive++;
4163 4164 4165
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4166 4167 4168 4169 4170

    return numInactive;
}

static int
4171 4172
testConnectListDefinedStoragePools(virConnectPtr conn,
                                   char **const names,
4173 4174
                                   int nnames)
{
4175
    testDriverPtr privconn = conn->privateData;
4176 4177
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
4178

4179
    testDriverLock(privconn);
C
Cole Robinson 已提交
4180
    memset(names, 0, sizeof(*names)*nnames);
4181
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
4182
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4183
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
4184
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
4185
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
4186
            goto error;
4187 4188 4189 4190
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4191 4192 4193

    return n;

4194
 error:
4195
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
4196
        VIR_FREE(names[n]);
4197
    testDriverUnlock(privconn);
4198
    return -1;
C
Cole Robinson 已提交
4199 4200
}

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

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

    testDriverLock(privconn);
4212 4213
    ret = virStoragePoolObjListExport(conn, privconn->pools, pools,
                                      NULL, flags);
4214 4215 4216 4217
    testDriverUnlock(privconn);

    return ret;
}
C
Cole Robinson 已提交
4218

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

    testDriverLock(privconn);
    obj = virStoragePoolObjFindByUUID(&privconn->pools, pool->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
4229
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4230 4231 4232 4233
        goto cleanup;
    }
    ret = virStoragePoolObjIsActive(obj);

4234
 cleanup:
4235 4236 4237 4238 4239 4240 4241
    if (obj)
        virStoragePoolObjUnlock(obj);
    return ret;
}

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

    testDriverLock(privconn);
    obj = virStoragePoolObjFindByUUID(&privconn->pools, pool->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
4250
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4251 4252 4253 4254
        goto cleanup;
    }
    ret = obj->configFile ? 1 : 0;

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



C
Cole Robinson 已提交
4263
static int
4264 4265
testStoragePoolCreate(virStoragePoolPtr pool,
                      unsigned int flags)
E
Eric Blake 已提交
4266
{
4267
    testDriverPtr privconn = pool->conn->privateData;
4268
    virStoragePoolObjPtr privpool;
4269
    int ret = -1;
4270
    virObjectEventPtr event = NULL;
4271

E
Eric Blake 已提交
4272 4273
    virCheckFlags(0, -1);

4274
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4275
        goto cleanup;
4276

4277
    if (virStoragePoolObjIsActive(privpool)) {
4278 4279
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4280 4281
        goto cleanup;
    }
C
Cole Robinson 已提交
4282 4283

    privpool->active = 1;
4284 4285 4286 4287

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

4290
 cleanup:
4291
    testObjectEventQueue(privconn, event);
4292 4293
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4294
    return ret;
C
Cole Robinson 已提交
4295 4296 4297
}

static char *
4298 4299 4300 4301
testConnectFindStoragePoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type,
                                  const char *srcSpec,
                                  unsigned int flags)
C
Cole Robinson 已提交
4302
{
4303 4304 4305 4306
    virStoragePoolSourcePtr source = NULL;
    int pool_type;
    char *ret = NULL;

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

4309 4310
    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
4311 4312
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
4313 4314 4315 4316
        goto cleanup;
    }

    if (srcSpec) {
4317
        source = virStoragePoolDefParseSourceString(srcSpec, pool_type);
4318 4319 4320 4321 4322 4323 4324
        if (!source)
            goto cleanup;
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
4325
        ignore_value(VIR_STRDUP(ret, defaultPoolSourcesLogicalXML));
4326 4327 4328
        break;

    case VIR_STORAGE_POOL_NETFS:
4329
        if (!source || !source->hosts[0].name) {
4330 4331
            virReportError(VIR_ERR_INVALID_ARG,
                           "%s", _("hostname must be specified for netfs sources"));
4332 4333 4334
            goto cleanup;
        }

4335 4336
        ignore_value(virAsprintf(&ret, defaultPoolSourcesNetFSXML,
                                 source->hosts[0].name));
4337 4338 4339
        break;

    default:
4340 4341
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source discovery"), type);
4342 4343
    }

4344
 cleanup:
4345 4346
    virStoragePoolSourceFree(source);
    return ret;
C
Cole Robinson 已提交
4347 4348 4349 4350
}


static virStoragePoolPtr
4351 4352 4353
testStoragePoolCreateXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4354
{
4355
    testDriverPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4356
    virStoragePoolDefPtr def;
4357
    virStoragePoolObjPtr pool = NULL;
4358
    virStoragePoolPtr ret = NULL;
4359
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
4360

E
Eric Blake 已提交
4361 4362
    virCheckFlags(0, NULL);

4363
    testDriverLock(privconn);
4364
    if (!(def = virStoragePoolDefParseString(xml)))
4365
        goto cleanup;
C
Cole Robinson 已提交
4366

4367 4368 4369 4370
    pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid);
    if (!pool)
        pool = virStoragePoolObjFindByName(&privconn->pools, def->name);
    if (pool) {
4371 4372
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("storage pool already exists"));
4373
        goto cleanup;
C
Cole Robinson 已提交
4374 4375
    }

4376
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4377
        goto cleanup;
4378
    def = NULL;
C
Cole Robinson 已提交
4379

4380
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4381
        virStoragePoolObjRemove(&privconn->pools, pool);
4382 4383
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4384 4385 4386
    }
    pool->active = 1;

4387 4388 4389 4390
    event = virStoragePoolEventLifecycleNew(pool->def->name, pool->def->uuid,
                                            VIR_STORAGE_POOL_EVENT_STARTED,
                                            0);

4391 4392
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4393

4394
 cleanup:
4395
    virStoragePoolDefFree(def);
4396
    testObjectEventQueue(privconn, event);
4397 4398 4399
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4400
    return ret;
C
Cole Robinson 已提交
4401 4402 4403
}

static virStoragePoolPtr
4404 4405 4406
testStoragePoolDefineXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4407
{
4408
    testDriverPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4409
    virStoragePoolDefPtr def;
4410
    virStoragePoolObjPtr pool = NULL;
4411
    virStoragePoolPtr ret = NULL;
4412
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
4413

E
Eric Blake 已提交
4414 4415
    virCheckFlags(0, NULL);

4416
    testDriverLock(privconn);
4417
    if (!(def = virStoragePoolDefParseString(xml)))
4418
        goto cleanup;
C
Cole Robinson 已提交
4419 4420 4421 4422 4423

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

4424
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4425 4426
        goto cleanup;
    def = NULL;
C
Cole Robinson 已提交
4427

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

4432
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4433
        virStoragePoolObjRemove(&privconn->pools, pool);
4434 4435
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4436 4437
    }

4438 4439
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4440

4441
 cleanup:
4442
    virStoragePoolDefFree(def);
4443
    testObjectEventQueue(privconn, event);
4444 4445 4446
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4447
    return ret;
C
Cole Robinson 已提交
4448 4449 4450
}

static int
4451 4452
testStoragePoolUndefine(virStoragePoolPtr pool)
{
4453
    testDriverPtr privconn = pool->conn->privateData;
4454
    virStoragePoolObjPtr privpool;
4455
    int ret = -1;
4456
    virObjectEventPtr event = NULL;
4457

4458
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4459
        goto cleanup;
4460

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

4467 4468 4469 4470
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_UNDEFINED,
                                            0);

C
Cole Robinson 已提交
4471
    virStoragePoolObjRemove(&privconn->pools, privpool);
4472
    privpool = NULL;
4473
    ret = 0;
C
Cole Robinson 已提交
4474

4475
 cleanup:
4476 4477
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4478
    testObjectEventQueue(privconn, event);
4479
    testDriverUnlock(privconn);
4480
    return ret;
C
Cole Robinson 已提交
4481 4482 4483
}

static int
4484
testStoragePoolBuild(virStoragePoolPtr pool,
E
Eric Blake 已提交
4485 4486
                     unsigned int flags)
{
4487
    testDriverPtr privconn = pool->conn->privateData;
4488
    virStoragePoolObjPtr privpool;
4489
    int ret = -1;
4490

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

4493
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4494
        goto cleanup;
4495

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

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


static int
4511 4512
testStoragePoolDestroy(virStoragePoolPtr pool)
{
4513
    testDriverPtr privconn = pool->conn->privateData;
4514
    virStoragePoolObjPtr privpool;
4515
    int ret = -1;
4516
    virObjectEventPtr event = NULL;
4517

4518
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4519
        goto cleanup;
4520 4521

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

    privpool->active = 0;
4528 4529 4530
    event = virStoragePoolEventLifecycleNew(privpool->def->name, privpool->def->uuid,
                                            VIR_STORAGE_POOL_EVENT_STOPPED,
                                            0);
C
Cole Robinson 已提交
4531

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

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


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

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

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

    if (virStoragePoolObjIsActive(privpool)) {
4561 4562
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4563
        goto cleanup;
4564 4565
    }

4566
    ret = 0;
C
Cole Robinson 已提交
4567

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


static int
4576
testStoragePoolRefresh(virStoragePoolPtr pool,
E
Eric Blake 已提交
4577 4578
                       unsigned int flags)
{
4579
    testDriverPtr privconn = pool->conn->privateData;
4580
    virStoragePoolObjPtr privpool;
4581
    int ret = -1;
4582
    virObjectEventPtr event = NULL;
4583

E
Eric Blake 已提交
4584 4585
    virCheckFlags(0, -1);

4586
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4587
        goto cleanup;
4588 4589

    if (!virStoragePoolObjIsActive(privpool)) {
4590 4591
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4592
        goto cleanup;
4593
    }
4594

4595
    event = virStoragePoolEventRefreshNew(pool->name, pool->uuid);
4596
    ret = 0;
C
Cole Robinson 已提交
4597

4598
 cleanup:
4599
    testObjectEventQueue(privconn, event);
4600 4601
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4602
    return ret;
C
Cole Robinson 已提交
4603 4604 4605 4606
}


static int
4607
testStoragePoolGetInfo(virStoragePoolPtr pool,
4608 4609
                       virStoragePoolInfoPtr info)
{
4610
    testDriverPtr privconn = pool->conn->privateData;
4611
    virStoragePoolObjPtr privpool;
4612
    int ret = -1;
4613

4614
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4615
        goto cleanup;
C
Cole Robinson 已提交
4616 4617 4618 4619 4620 4621 4622 4623 4624

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

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

static char *
4634
testStoragePoolGetXMLDesc(virStoragePoolPtr pool,
E
Eric Blake 已提交
4635 4636
                          unsigned int flags)
{
4637
    testDriverPtr privconn = pool->conn->privateData;
4638
    virStoragePoolObjPtr privpool;
4639
    char *ret = NULL;
4640

E
Eric Blake 已提交
4641 4642
    virCheckFlags(0, NULL);

4643
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4644
        goto cleanup;
4645

4646
    ret = virStoragePoolDefFormat(privpool->def);
4647

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

static int
4655
testStoragePoolGetAutostart(virStoragePoolPtr pool,
4656 4657
                            int *autostart)
{
4658
    testDriverPtr privconn = pool->conn->privateData;
4659
    virStoragePoolObjPtr privpool;
4660
    int ret = -1;
4661

4662
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4663
        goto cleanup;
C
Cole Robinson 已提交
4664 4665 4666 4667 4668 4669

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

4672
 cleanup:
4673 4674
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4675
    return ret;
C
Cole Robinson 已提交
4676 4677 4678
}

static int
4679
testStoragePoolSetAutostart(virStoragePoolPtr pool,
4680 4681
                            int autostart)
{
4682
    testDriverPtr privconn = pool->conn->privateData;
4683
    virStoragePoolObjPtr privpool;
4684
    int ret = -1;
4685

4686
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4687
        goto cleanup;
C
Cole Robinson 已提交
4688 4689

    if (!privpool->configFile) {
4690 4691
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("pool has no config file"));
4692
        goto cleanup;
C
Cole Robinson 已提交
4693 4694 4695 4696
    }

    autostart = (autostart != 0);
    privpool->autostart = autostart;
4697 4698
    ret = 0;

4699
 cleanup:
4700 4701
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4702
    return ret;
C
Cole Robinson 已提交
4703 4704 4705 4706
}


static int
4707 4708
testStoragePoolNumOfVolumes(virStoragePoolPtr pool)
{
4709
    testDriverPtr privconn = pool->conn->privateData;
4710
    virStoragePoolObjPtr privpool;
4711
    int ret = -1;
4712

4713
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4714
        goto cleanup;
4715 4716

    if (!virStoragePoolObjIsActive(privpool)) {
4717 4718
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4719
        goto cleanup;
4720
    }
C
Cole Robinson 已提交
4721

4722 4723
    ret = privpool->volumes.count;

4724
 cleanup:
4725 4726
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4727
    return ret;
C
Cole Robinson 已提交
4728 4729 4730
}

static int
4731
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4732
                           char **const names,
4733 4734
                           int maxnames)
{
4735
    testDriverPtr privconn = pool->conn->privateData;
4736
    virStoragePoolObjPtr privpool;
4737 4738
    size_t i = 0;
    int n = 0;
C
Cole Robinson 已提交
4739

4740
    memset(names, 0, maxnames * sizeof(*names));
4741

4742
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4743
        goto cleanup;
4744 4745

    if (!virStoragePoolObjIsActive(privpool)) {
4746 4747
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4748
        goto cleanup;
4749 4750
    }

4751
    for (i = 0; i < privpool->volumes.count && n < maxnames; i++) {
4752
        if (VIR_STRDUP(names[n++], privpool->volumes.objs[i]->name) < 0)
C
Cole Robinson 已提交
4753 4754 4755
            goto cleanup;
    }

4756
    virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4757 4758 4759
    return n;

 cleanup:
4760
    for (n = 0; n < maxnames; n++)
C
Cole Robinson 已提交
4761 4762
        VIR_FREE(names[i]);

4763
    memset(names, 0, maxnames * sizeof(*names));
4764 4765
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4766 4767 4768
    return -1;
}

4769 4770 4771
static int
testStoragePoolListAllVolumes(virStoragePoolPtr obj,
                              virStorageVolPtr **vols,
4772 4773
                              unsigned int flags)
{
4774
    testDriverPtr privconn = obj->conn->privateData;
4775
    virStoragePoolObjPtr pool;
4776
    size_t i;
4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805
    virStorageVolPtr *tmp_vols = NULL;
    virStorageVolPtr vol = NULL;
    int nvols = 0;
    int ret = -1;

    virCheckFlags(0, -1);

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

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

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

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

4806
    if (VIR_ALLOC_N(tmp_vols, pool->volumes.count + 1) < 0)
4807 4808
         goto cleanup;

4809
    for (i = 0; i < pool->volumes.count; i++) {
4810 4811
        if (!(vol = virGetStorageVol(obj->conn, pool->def->name,
                                     pool->volumes.objs[i]->name,
4812 4813
                                     pool->volumes.objs[i]->key,
                                     NULL, NULL)))
4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827
            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]);
        }
4828
        VIR_FREE(tmp_vols);
4829 4830 4831 4832 4833 4834 4835
    }

    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
C
Cole Robinson 已提交
4836 4837

static virStorageVolPtr
4838
testStorageVolLookupByName(virStoragePoolPtr pool,
4839 4840
                           const char *name ATTRIBUTE_UNUSED)
{
4841
    testDriverPtr privconn = pool->conn->privateData;
4842 4843
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
4844
    virStorageVolPtr ret = NULL;
4845

4846
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4847
        goto cleanup;
4848 4849

    if (!virStoragePoolObjIsActive(privpool)) {
4850 4851
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4852
        goto cleanup;
4853 4854 4855 4856 4857
    }

    privvol = virStorageVolDefFindByName(privpool, name);

    if (!privvol) {
4858 4859
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"), name);
4860
        goto cleanup;
C
Cole Robinson 已提交
4861 4862
    }

4863
    ret = virGetStorageVol(pool->conn, privpool->def->name,
4864 4865
                           privvol->name, privvol->key,
                           NULL, NULL);
4866

4867
 cleanup:
4868 4869
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4870
    return ret;
C
Cole Robinson 已提交
4871 4872 4873 4874
}


static virStorageVolPtr
4875
testStorageVolLookupByKey(virConnectPtr conn,
4876 4877
                          const char *key)
{
4878
    testDriverPtr privconn = conn->privateData;
4879
    size_t i;
4880
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4881

4882
    testDriverLock(privconn);
4883
    for (i = 0; i < privconn->pools.count; i++) {
4884
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4885
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4886
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4887 4888
                virStorageVolDefFindByKey(privconn->pools.objs[i], key);

4889 4890 4891 4892
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
4893 4894
                                       privvol->key,
                                       NULL, NULL);
4895
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
4896 4897
                break;
            }
C
Cole Robinson 已提交
4898
        }
4899
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4900
    }
4901
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4902

4903
    if (!ret)
4904 4905
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching key '%s'"), key);
4906 4907

    return ret;
C
Cole Robinson 已提交
4908 4909 4910
}

static virStorageVolPtr
4911
testStorageVolLookupByPath(virConnectPtr conn,
4912 4913
                           const char *path)
{
4914
    testDriverPtr privconn = conn->privateData;
4915
    size_t i;
4916
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4917

4918
    testDriverLock(privconn);
4919
    for (i = 0; i < privconn->pools.count; i++) {
4920
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4921
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4922
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4923 4924
                virStorageVolDefFindByPath(privconn->pools.objs[i], path);

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

4939
    if (!ret)
4940 4941
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching path '%s'"), path);
4942 4943

    return ret;
C
Cole Robinson 已提交
4944 4945 4946
}

static virStorageVolPtr
4947 4948 4949
testStorageVolCreateXML(virStoragePoolPtr pool,
                        const char *xmldesc,
                        unsigned int flags)
E
Eric Blake 已提交
4950
{
4951
    testDriverPtr privconn = pool->conn->privateData;
4952
    virStoragePoolObjPtr privpool;
4953 4954
    virStorageVolDefPtr privvol = NULL;
    virStorageVolPtr ret = NULL;
4955

E
Eric Blake 已提交
4956 4957
    virCheckFlags(0, NULL);

4958
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
4959
        goto cleanup;
4960 4961

    if (!virStoragePoolObjIsActive(privpool)) {
4962 4963
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4964
        goto cleanup;
4965
    }
C
Cole Robinson 已提交
4966

4967
    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
4968
    if (privvol == NULL)
4969
        goto cleanup;
4970 4971

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
4972 4973
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
4974
        goto cleanup;
C
Cole Robinson 已提交
4975 4976 4977
    }

    /* Make sure enough space */
4978
    if ((privpool->def->allocation + privvol->target.allocation) >
C
Cole Robinson 已提交
4979
         privpool->def->capacity) {
4980 4981 4982
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
4983
        goto cleanup;
C
Cole Robinson 已提交
4984 4985
    }

4986 4987
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
4988
                    privvol->name) == -1)
4989
        goto cleanup;
C
Cole Robinson 已提交
4990

4991 4992 4993
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
        VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
                                privpool->volumes.count, privvol) < 0)
4994
        goto cleanup;
C
Cole Robinson 已提交
4995

4996
    privpool->def->allocation += privvol->target.allocation;
C
Cole Robinson 已提交
4997 4998 4999
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

5000
    ret = virGetStorageVol(pool->conn, privpool->def->name,
5001 5002
                           privvol->name, privvol->key,
                           NULL, NULL);
5003
    privvol = NULL;
5004

5005
 cleanup:
5006
    virStorageVolDefFree(privvol);
5007 5008
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5009
    return ret;
C
Cole Robinson 已提交
5010 5011
}

5012
static virStorageVolPtr
5013 5014 5015 5016
testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
                            const char *xmldesc,
                            virStorageVolPtr clonevol,
                            unsigned int flags)
E
Eric Blake 已提交
5017
{
5018
    testDriverPtr privconn = pool->conn->privateData;
5019 5020 5021 5022
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol = NULL, origvol = NULL;
    virStorageVolPtr ret = NULL;

E
Eric Blake 已提交
5023 5024
    virCheckFlags(0, NULL);

5025
    if (!(privpool = testStoragePoolObjFindByName(privconn, pool->name)))
5026 5027 5028
        goto cleanup;

    if (!virStoragePoolObjIsActive(privpool)) {
5029 5030
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
5031 5032 5033
        goto cleanup;
    }

5034
    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
5035 5036 5037 5038
    if (privvol == NULL)
        goto cleanup;

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

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

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

5063 5064
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
5065
                    privvol->name) == -1)
5066 5067
        goto cleanup;

5068 5069 5070
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
        VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
                                privpool->volumes.count, privvol) < 0)
5071 5072
        goto cleanup;

5073
    privpool->def->allocation += privvol->target.allocation;
5074 5075 5076 5077
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    ret = virGetStorageVol(pool->conn, privpool->def->name,
5078 5079
                           privvol->name, privvol->key,
                           NULL, NULL);
5080 5081
    privvol = NULL;

5082
 cleanup:
5083 5084 5085 5086 5087 5088
    virStorageVolDefFree(privvol);
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    return ret;
}

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

E
Eric Blake 已提交
5099 5100
    virCheckFlags(0, -1);

5101
    if (!(privpool = testStoragePoolObjFindByName(privconn, vol->pool)))
5102
        goto cleanup;
5103 5104 5105 5106

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

    if (privvol == NULL) {
5107 5108 5109
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5110
        goto cleanup;
5111 5112 5113
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5114 5115
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5116
        goto cleanup;
5117 5118 5119
    }


5120
    privpool->def->allocation -= privvol->target.allocation;
C
Cole Robinson 已提交
5121 5122 5123
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

5124
    for (i = 0; i < privpool->volumes.count; i++) {
C
Cole Robinson 已提交
5125 5126 5127
        if (privpool->volumes.objs[i] == privvol) {
            virStorageVolDefFree(privvol);

5128
            VIR_DELETE_ELEMENT(privpool->volumes.objs, i, privpool->volumes.count);
C
Cole Robinson 已提交
5129 5130 5131
            break;
        }
    }
5132
    ret = 0;
C
Cole Robinson 已提交
5133

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


5141 5142
static int testStorageVolumeTypeForPool(int pooltype)
{
C
Cole Robinson 已提交
5143

5144
    switch (pooltype) {
C
Cole Robinson 已提交
5145 5146 5147 5148 5149 5150 5151 5152 5153 5154
        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
5155
testStorageVolGetInfo(virStorageVolPtr vol,
5156 5157
                      virStorageVolInfoPtr info)
{
5158
    testDriverPtr privconn = vol->conn->privateData;
5159 5160
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5161
    int ret = -1;
5162

5163
    if (!(privpool = testStoragePoolObjFindByName(privconn, vol->pool)))
5164
        goto cleanup;
5165 5166 5167 5168

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

    if (privvol == NULL) {
5169 5170 5171
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5172
        goto cleanup;
5173 5174 5175
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5176 5177
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5178
        goto cleanup;
5179
    }
C
Cole Robinson 已提交
5180 5181 5182

    memset(info, 0, sizeof(*info));
    info->type = testStorageVolumeTypeForPool(privpool->def->type);
5183 5184
    info->capacity = privvol->target.capacity;
    info->allocation = privvol->target.allocation;
5185
    ret = 0;
C
Cole Robinson 已提交
5186

5187
 cleanup:
5188 5189
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5190
    return ret;
C
Cole Robinson 已提交
5191 5192 5193
}

static char *
5194 5195
testStorageVolGetXMLDesc(virStorageVolPtr vol,
                         unsigned int flags)
E
Eric Blake 已提交
5196
{
5197
    testDriverPtr privconn = vol->conn->privateData;
5198 5199
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5200
    char *ret = NULL;
5201

E
Eric Blake 已提交
5202 5203
    virCheckFlags(0, NULL);

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

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

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

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

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

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

static char *
5231 5232
testStorageVolGetPath(virStorageVolPtr vol)
{
5233
    testDriverPtr privconn = vol->conn->privateData;
5234 5235
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5236
    char *ret = NULL;
5237

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

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

    if (privvol == NULL) {
5244 5245 5246
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5247
        goto cleanup;
5248 5249 5250
    }

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

5256
    ignore_value(VIR_STRDUP(ret, privvol->target.path));
5257

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

5264

5265
/* Node device implementations */
5266

5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285
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;
}


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

E
Eric Blake 已提交
5295 5296
    virCheckFlags(0, -1);

5297 5298 5299
    testDriverLock(driver);
    for (i = 0; i < driver->devs.count; i++)
        if ((cap == NULL) ||
5300
            virNodeDeviceObjHasCap(driver->devs.objs[i], cap))
5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311
            ++ndevs;
    testDriverUnlock(driver);

    return ndevs;
}

static int
testNodeListDevices(virConnectPtr conn,
                    const char *cap,
                    char **const names,
                    int maxnames,
E
Eric Blake 已提交
5312
                    unsigned int flags)
5313
{
5314
    testDriverPtr driver = conn->privateData;
5315
    int ndevs = 0;
5316
    size_t i;
5317

E
Eric Blake 已提交
5318 5319
    virCheckFlags(0, -1);

5320 5321 5322 5323
    testDriverLock(driver);
    for (i = 0; i < driver->devs.count && ndevs < maxnames; i++) {
        virNodeDeviceObjLock(driver->devs.objs[i]);
        if (cap == NULL ||
5324
            virNodeDeviceObjHasCap(driver->devs.objs[i], cap)) {
5325
            if (VIR_STRDUP(names[ndevs++], driver->devs.objs[i]->def->name) < 0) {
5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346
                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)
{
5347
    testDriverPtr driver = conn->privateData;
5348 5349 5350
    virNodeDeviceObjPtr obj;
    virNodeDevicePtr ret = NULL;

5351
    if (!(obj = testNodeDeviceObjFindByName(driver, name)))
5352 5353
        goto cleanup;

5354 5355 5356 5357
    if ((ret = virGetNodeDevice(conn, name))) {
        if (VIR_STRDUP(ret->parent, obj->def->parent) < 0)
            virObjectUnref(ret);
    }
5358

5359
 cleanup:
5360 5361 5362 5363 5364 5365
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

static char *
5366
testNodeDeviceGetXMLDesc(virNodeDevicePtr dev,
E
Eric Blake 已提交
5367
                         unsigned int flags)
5368
{
5369
    testDriverPtr driver = dev->conn->privateData;
5370 5371 5372
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

E
Eric Blake 已提交
5373 5374
    virCheckFlags(0, NULL);

5375
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5376 5377
        goto cleanup;

5378
    ret = virNodeDeviceDefFormat(obj->def);
5379

5380
 cleanup:
5381 5382 5383 5384 5385 5386 5387 5388
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

static char *
testNodeDeviceGetParent(virNodeDevicePtr dev)
{
5389
    testDriverPtr driver = dev->conn->privateData;
5390 5391 5392
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

5393
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5394 5395 5396
        goto cleanup;

    if (obj->def->parent) {
5397
        ignore_value(VIR_STRDUP(ret, obj->def->parent));
5398
    } else {
5399 5400
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no parent for this device"));
5401 5402
    }

5403
 cleanup:
5404 5405 5406 5407 5408
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

5409

5410 5411 5412
static int
testNodeDeviceNumOfCaps(virNodeDevicePtr dev)
{
5413
    testDriverPtr driver = dev->conn->privateData;
5414 5415 5416 5417 5418
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

5419
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5420 5421 5422 5423 5424 5425
        goto cleanup;

    for (caps = obj->def->caps; caps; caps = caps->next)
        ++ncaps;
    ret = ncaps;

5426
 cleanup:
5427 5428 5429 5430 5431 5432 5433 5434 5435
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}


static int
testNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
5436
    testDriverPtr driver = dev->conn->privateData;
5437 5438 5439 5440 5441
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

5442
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5443 5444 5445
        goto cleanup;

    for (caps = obj->def->caps; caps && ncaps < maxnames; caps = caps->next) {
5446
        if (VIR_STRDUP(names[ncaps++], virNodeDevCapTypeToString(caps->data.type)) < 0)
5447 5448 5449 5450
            goto cleanup;
    }
    ret = ncaps;

5451
 cleanup:
5452 5453 5454 5455 5456 5457 5458 5459 5460 5461
    if (obj)
        virNodeDeviceObjUnlock(obj);
    if (ret == -1) {
        --ncaps;
        while (--ncaps >= 0)
            VIR_FREE(names[ncaps]);
    }
    return ret;
}

5462

5463 5464
static virNodeDeviceObjPtr
testNodeDeviceMockCreateVport(testDriverPtr driver,
5465
                              const char *wwnn,
5466
                              const char *wwpn)
5467
{
5468 5469
    char *xml = NULL;
    virNodeDeviceDefPtr def = NULL;
5470
    virNodeDevCapsDefPtr caps;
5471
    virNodeDeviceObjPtr obj = NULL, objcopy = NULL;
5472
    virObjectEventPtr event = NULL;
5473

5474 5475 5476 5477 5478 5479 5480 5481 5482
    /* 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. */
5483
    if (!(objcopy = virNodeDeviceObjFindByName(&driver->devs, "scsi_host11")))
5484 5485 5486 5487 5488 5489 5490 5491
        goto cleanup;

    xml = virNodeDeviceDefFormat(objcopy->def);
    virNodeDeviceObjUnlock(objcopy);
    if (!xml)
        goto cleanup;

    if (!(def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL)))
5492 5493
        goto cleanup;

5494
    VIR_FREE(def->name);
5495
    if (VIR_STRDUP(def->name, "scsi_host12") < 0)
5496 5497
        goto cleanup;

5498 5499 5500
    /* 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. */
5501 5502
    caps = def->caps;
    while (caps) {
5503
        if (caps->data.type != VIR_NODE_DEV_CAP_SCSI_HOST)
5504 5505
            continue;

5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519
        /* 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++;
        }
5520 5521 5522
        caps = caps->next;
    }

5523
    if (!(obj = virNodeDeviceObjAssignDef(&driver->devs, def)))
5524
        goto cleanup;
5525
    def = NULL;
5526

5527
    event = virNodeDeviceEventLifecycleNew(obj->def->name,
5528 5529
                                           VIR_NODE_DEVICE_EVENT_CREATED,
                                           0);
5530 5531 5532
    testObjectEventQueue(driver, event);

 cleanup:
5533
    VIR_FREE(xml);
5534 5535
    virNodeDeviceDefFree(def);
    return obj;
5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546
}


static virNodeDevicePtr
testNodeDeviceCreateXML(virConnectPtr conn,
                        const char *xmlDesc,
                        unsigned int flags)
{
    testDriverPtr driver = conn->privateData;
    virNodeDeviceDefPtr def = NULL;
    char *wwnn = NULL, *wwpn = NULL;
5547 5548
    virNodeDevicePtr dev = NULL, ret = NULL;
    virNodeDeviceObjPtr obj = NULL;
5549 5550 5551 5552 5553 5554 5555 5556

    virCheckFlags(0, NULL);

    testDriverLock(driver);

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

5557 5558 5559
    /* We run this simply for validation - it essentially validates that
     * the input XML either has a wwnn/wwpn or virNodeDevCapSCSIHostParseXML
     * generated a wwnn/wwpn */
5560 5561 5562
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) < 0)
        goto cleanup;

5563 5564 5565
    /* 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. */
5566
    if (virNodeDeviceObjGetParentHost(&driver->devs, def, CREATE_DEVICE) < 0)
5567 5568 5569 5570
        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
5571 5572 5573
     * 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 */
5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585
    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;
5586

5587
 cleanup:
5588 5589
    if (obj)
        virNodeDeviceObjUnlock(obj);
5590
    testDriverUnlock(driver);
5591
    virNodeDeviceDefFree(def);
5592
    virObjectUnref(dev);
5593 5594
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
5595
    return ret;
5596 5597 5598 5599 5600 5601
}

static int
testNodeDeviceDestroy(virNodeDevicePtr dev)
{
    int ret = 0;
5602
    testDriverPtr driver = dev->conn->privateData;
5603 5604
    virNodeDeviceObjPtr obj = NULL;
    char *parent_name = NULL, *wwnn = NULL, *wwpn = NULL;
5605
    virObjectEventPtr event = NULL;
5606

5607
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5608 5609
        goto out;

5610
    if (virNodeDeviceGetWWNs(obj->def, &wwnn, &wwpn) == -1)
5611 5612
        goto out;

5613
    if (VIR_STRDUP(parent_name, obj->def->parent) < 0)
5614 5615 5616 5617 5618 5619 5620 5621
        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);

5622 5623
    /* We do this just for basic validation, but also avoid finding a
     * vport capable HBA if for some reason our vHBA doesn't exist */
5624 5625
    if (virNodeDeviceObjGetParentHost(&driver->devs, obj->def,
                                      EXISTING_DEVICE) < 0) {
5626 5627 5628 5629
        obj = NULL;
        goto out;
    }

5630 5631 5632 5633
    event = virNodeDeviceEventLifecycleNew(dev->name,
                                           VIR_NODE_DEVICE_EVENT_DELETED,
                                           0);

5634
    virNodeDeviceObjLock(obj);
5635
    virNodeDeviceObjRemove(&driver->devs, &obj);
5636

5637
 out:
5638 5639
    if (obj)
        virNodeDeviceObjUnlock(obj);
5640
    testObjectEventQueue(driver, event);
5641 5642 5643 5644 5645 5646
    VIR_FREE(parent_name);
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return ret;
}

5647 5648

/* Domain event implementations */
5649
static int
5650 5651 5652 5653
testConnectDomainEventRegister(virConnectPtr conn,
                               virConnectDomainEventCallback callback,
                               void *opaque,
                               virFreeCallback freecb)
5654
{
5655
    testDriverPtr driver = conn->privateData;
5656
    int ret = 0;
5657

5658
    if (virDomainEventStateRegister(conn, driver->eventState,
5659 5660
                                    callback, opaque, freecb) < 0)
        ret = -1;
5661 5662 5663 5664

    return ret;
}

5665

5666
static int
5667 5668
testConnectDomainEventDeregister(virConnectPtr conn,
                                 virConnectDomainEventCallback callback)
5669
{
5670
    testDriverPtr driver = conn->privateData;
5671
    int ret = 0;
5672

5673
    if (virDomainEventStateDeregister(conn, driver->eventState,
5674 5675
                                      callback) < 0)
        ret = -1;
5676 5677 5678 5679

    return ret;
}

5680 5681

static int
5682 5683 5684 5685 5686 5687
testConnectDomainEventRegisterAny(virConnectPtr conn,
                                  virDomainPtr dom,
                                  int eventID,
                                  virConnectDomainEventGenericCallback callback,
                                  void *opaque,
                                  virFreeCallback freecb)
5688
{
5689
    testDriverPtr driver = conn->privateData;
5690 5691
    int ret;

5692
    if (virDomainEventStateRegisterID(conn, driver->eventState,
5693 5694
                                      dom, eventID,
                                      callback, opaque, freecb, &ret) < 0)
5695
        ret = -1;
5696 5697 5698 5699 5700

    return ret;
}

static int
5701 5702
testConnectDomainEventDeregisterAny(virConnectPtr conn,
                                    int callbackID)
5703
{
5704
    testDriverPtr driver = conn->privateData;
5705
    int ret = 0;
5706

5707
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5708 5709
                                        callbackID) < 0)
        ret = -1;
5710 5711 5712 5713 5714

    return ret;
}


5715 5716 5717 5718 5719 5720 5721 5722
static int
testConnectNetworkEventRegisterAny(virConnectPtr conn,
                                   virNetworkPtr net,
                                   int eventID,
                                   virConnectNetworkEventGenericCallback callback,
                                   void *opaque,
                                   virFreeCallback freecb)
{
5723
    testDriverPtr driver = conn->privateData;
5724 5725
    int ret;

5726
    if (virNetworkEventStateRegisterID(conn, driver->eventState,
5727
                                       net, eventID, callback,
5728 5729 5730 5731 5732 5733 5734 5735 5736 5737
                                       opaque, freecb, &ret) < 0)
        ret = -1;

    return ret;
}

static int
testConnectNetworkEventDeregisterAny(virConnectPtr conn,
                                     int callbackID)
{
5738
    testDriverPtr driver = conn->privateData;
5739
    int ret = 0;
5740

5741
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5742 5743
                                        callbackID) < 0)
        ret = -1;
5744 5745 5746 5747

    return ret;
}

5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780
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;
}

5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813
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;
}

5814 5815 5816
static int testConnectListAllDomains(virConnectPtr conn,
                                     virDomainPtr **domains,
                                     unsigned int flags)
5817
{
5818
    testDriverPtr privconn = conn->privateData;
5819

O
Osier Yang 已提交
5820
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
5821

5822 5823
    return virDomainObjListExport(privconn->domains, conn, domains,
                                  NULL, flags);
5824 5825
}

5826
static int
P
Peter Krempa 已提交
5827
testNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,
5828 5829 5830 5831 5832 5833 5834
                  unsigned char **cpumap,
                  unsigned int *online,
                  unsigned int flags)
{
    virCheckFlags(0, -1);

    if (cpumap) {
5835
        if (VIR_ALLOC_N(*cpumap, 1) < 0)
P
Peter Krempa 已提交
5836
            return -1;
5837 5838 5839 5840 5841 5842
        *cpumap[0] = 0x15;
    }

    if (online)
        *online = 3;

P
Peter Krempa 已提交
5843
    return  8;
5844 5845
}

5846 5847 5848 5849 5850 5851 5852 5853 5854 5855
static char *
testDomainScreenshot(virDomainPtr dom ATTRIBUTE_UNUSED,
                     virStreamPtr st,
                     unsigned int screen ATTRIBUTE_UNUSED,
                     unsigned int flags)
{
    char *ret = NULL;

    virCheckFlags(0, NULL);

5856
    if (VIR_STRDUP(ret, "image/png") < 0)
5857 5858
        return NULL;

D
Daniel P. Berrange 已提交
5859
    if (virFDStreamOpenFile(st, PKGDATADIR "/test-screenshot.png", 0, 0, O_RDONLY) < 0)
5860 5861 5862 5863 5864
        VIR_FREE(ret);

    return ret;
}

5865 5866
static int
testConnectGetCPUModelNames(virConnectPtr conn ATTRIBUTE_UNUSED,
J
Jiri Denemark 已提交
5867
                            const char *archName,
5868 5869 5870
                            char ***models,
                            unsigned int flags)
{
J
Jiri Denemark 已提交
5871 5872
    virArch arch;

5873
    virCheckFlags(0, -1);
J
Jiri Denemark 已提交
5874 5875 5876 5877 5878 5879 5880 5881

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

J
Jiri Denemark 已提交
5882
    return virCPUGetModels(arch, models);
5883
}
5884

C
Cole Robinson 已提交
5885 5886 5887
static int
testDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
5888
    testDriverPtr privconn = dom->conn->privateData;
C
Cole Robinson 已提交
5889
    virDomainObjPtr vm = NULL;
5890
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
5891 5892 5893 5894 5895 5896
    int ret = -1;

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

5897 5898
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912

    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);
5913
    event = virDomainEventLifecycleNewFromObj(vm,
C
Cole Robinson 已提交
5914 5915 5916 5917 5918
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
    vm->hasManagedSave = true;

    ret = 0;
5919
 cleanup:
5920
    virDomainObjEndAPI(&vm);
5921
    testObjectEventQueue(privconn, event);
C
Cole Robinson 已提交
5922 5923 5924 5925 5926 5927 5928 5929 5930

    return ret;
}


static int
testDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm;
5931
    int ret;
C
Cole Robinson 已提交
5932 5933 5934

    virCheckFlags(0, -1);

5935 5936
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5937 5938

    ret = vm->hasManagedSave;
5939

5940
    virDomainObjEndAPI(&vm);
C
Cole Robinson 已提交
5941 5942 5943 5944 5945 5946 5947 5948 5949 5950
    return ret;
}

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

    virCheckFlags(0, -1);

5951 5952
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5953 5954

    vm->hasManagedSave = false;
5955

5956
    virDomainObjEndAPI(&vm);
5957
    return 0;
C
Cole Robinson 已提交
5958 5959 5960
}


5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994
/*
 * 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;
5995
    int n;
5996 5997 5998 5999 6000

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6001
        return -1;
6002 6003 6004

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

6005
    virDomainObjEndAPI(&vm);
6006 6007 6008 6009 6010 6011 6012 6013 6014 6015
    return n;
}

static int
testDomainSnapshotListNames(virDomainPtr domain,
                            char **names,
                            int nameslen,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6016
    int n;
6017 6018 6019 6020 6021

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6022
        return -1;
6023 6024 6025 6026

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

6027
    virDomainObjEndAPI(&vm);
6028 6029 6030 6031 6032 6033 6034 6035 6036
    return n;
}

static int
testDomainListAllSnapshots(virDomainPtr domain,
                           virDomainSnapshotPtr **snaps,
                           unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6037
    int n;
6038 6039 6040 6041 6042

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6043
        return -1;
6044 6045 6046

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

6047
    virDomainObjEndAPI(&vm);
6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064
    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)))
6065
        return -1;
6066 6067 6068 6069 6070 6071 6072

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

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

6073
 cleanup:
6074
    virDomainObjEndAPI(&vm);
6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089
    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)))
6090
        return -1;
6091 6092 6093 6094 6095 6096

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

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

6097
 cleanup:
6098
    virDomainObjEndAPI(&vm);
6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114
    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)))
6115
        return -1;
6116 6117 6118 6119 6120 6121 6122

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

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

6123
 cleanup:
6124
    virDomainObjEndAPI(&vm);
6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139
    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)))
6140
        return NULL;
6141 6142 6143 6144 6145 6146

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

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

6147
 cleanup:
6148
    virDomainObjEndAPI(&vm);
6149 6150 6151 6152 6153 6154 6155 6156
    return snapshot;
}

static int
testDomainHasCurrentSnapshot(virDomainPtr domain,
                             unsigned int flags)
{
    virDomainObjPtr vm;
6157
    int ret;
6158 6159 6160 6161

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6162
        return -1;
6163 6164 6165

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

6166
    virDomainObjEndAPI(&vm);
6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180
    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)))
6181
        return NULL;
6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194

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

6195
 cleanup:
6196
    virDomainObjEndAPI(&vm);
6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209
    return parent;
}

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

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
6210
        return NULL;
6211 6212 6213 6214 6215 6216 6217 6218 6219

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

6220
 cleanup:
6221
    virDomainObjEndAPI(&vm);
6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232
    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];
6233
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6234 6235 6236 6237

    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6238
        return NULL;
6239 6240 6241 6242 6243 6244

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

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

6245
    xml = virDomainSnapshotDefFormat(uuidstr, snap->def, privconn->caps,
6246 6247
                                     virDomainDefFormatConvertXMLFlags(flags),
                                     0);
6248

6249
 cleanup:
6250
    virDomainObjEndAPI(&vm);
6251 6252 6253 6254 6255 6256 6257 6258
    return xml;
}

static int
testDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6259
    int ret;
6260 6261 6262 6263

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6264
        return -1;
6265 6266 6267 6268

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

6269
    virDomainObjEndAPI(&vm);
6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283
    return ret;
}


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

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6284
        return -1;
6285

C
Cole Robinson 已提交
6286
    if (!testSnapObjFromSnapshot(vm, snapshot))
6287 6288 6289 6290
        goto cleanup;

    ret = 1;

6291
 cleanup:
6292
    virDomainObjEndAPI(&vm);
6293 6294 6295
    return ret;
}

6296 6297 6298 6299 6300 6301
static int
testDomainSnapshotAlignDisks(virDomainObjPtr vm,
                             virDomainSnapshotDefPtr def,
                             unsigned int flags)
{
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
E
Eric Blake 已提交
6302
    bool align_match = true;
6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330

    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)
{
6331
    testDriverPtr privconn = domain->conn->privateData;
6332 6333 6334 6335
    virDomainObjPtr vm = NULL;
    virDomainSnapshotDefPtr def = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr snapshot = NULL;
6336
    virObjectEventPtr event = NULL;
6337
    char *xml = NULL;
6338 6339
    bool update_current = true;
    bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
6340 6341 6342 6343 6344 6345 6346 6347
    unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;

    /*
     * DISK_ONLY: Not implemented yet
     * REUSE_EXT: Not implemented yet
     *
     * NO_METADATA: Explicitly not implemented
     *
6348
     * REDEFINE + CURRENT: Implemented
6349 6350 6351 6352 6353 6354
     * HALT: Implemented
     * QUIESCE: Nothing to do
     * ATOMIC: Nothing to do
     * LIVE: Nothing to do
     */
    virCheckFlags(
6355 6356
        VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
        VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
6357 6358 6359 6360 6361
        VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
        VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
        VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
        VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, NULL);

6362 6363 6364 6365 6366
    if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)))
        update_current = false;
    if (redefine)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;

6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381
    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;

6382
    if (redefine) {
C
Cole Robinson 已提交
6383 6384
        if (virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
                                          &update_current, flags) < 0)
6385 6386 6387 6388 6389
            goto cleanup;
    } else {
        if (!(def->dom = virDomainDefCopy(vm->def,
                                          privconn->caps,
                                          privconn->xmlopt,
6390
                                          NULL,
6391 6392
                                          true)))
            goto cleanup;
6393

6394
        if (testDomainSnapshotAlignDisks(vm, def, flags) < 0)
6395 6396 6397
            goto cleanup;
    }

6398 6399 6400 6401
    if (!snap) {
        if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
            goto cleanup;
        def = NULL;
6402 6403
    }

6404 6405 6406 6407 6408 6409 6410 6411 6412 6413
    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);
6414
            event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
6415 6416 6417
                                    VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
        }
    }
6418 6419

    snapshot = virGetDomainSnapshot(domain, snap->def->name);
6420
 cleanup:
6421 6422 6423 6424
    VIR_FREE(xml);
    if (vm) {
        if (snapshot) {
            virDomainSnapshotObjPtr other;
6425 6426
            if (update_current)
                vm->current_snapshot = snap;
6427 6428 6429 6430 6431 6432 6433
            other = virDomainSnapshotFindByName(vm->snapshots,
                                                snap->def->parent);
            snap->parent = other;
            other->nchildren++;
            snap->sibling = other->first_child;
            other->first_child = snap;
        }
6434
        virDomainObjEndAPI(&vm);
6435
    }
6436
    testObjectEventQueue(privconn, event);
6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448
    virDomainSnapshotDefFree(def);
    return snapshot;
}


typedef struct _testSnapRemoveData testSnapRemoveData;
typedef testSnapRemoveData *testSnapRemoveDataPtr;
struct _testSnapRemoveData {
    virDomainObjPtr vm;
    bool current;
};

6449
static int
6450
testDomainSnapshotDiscardAll(void *payload,
6451 6452
                             const void *name ATTRIBUTE_UNUSED,
                             void *data)
6453 6454 6455 6456 6457 6458 6459
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapRemoveDataPtr curr = data;

    if (snap->def->current)
        curr->current = true;
    virDomainSnapshotObjListRemove(curr->vm->snapshots, snap);
6460
    return 0;
6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471
}

typedef struct _testSnapReparentData testSnapReparentData;
typedef testSnapReparentData *testSnapReparentDataPtr;
struct _testSnapReparentData {
    virDomainSnapshotObjPtr parent;
    virDomainObjPtr vm;
    int err;
    virDomainSnapshotObjPtr last;
};

6472
static int
6473 6474 6475 6476 6477 6478 6479
testDomainSnapshotReparentChildren(void *payload,
                                   const void *name ATTRIBUTE_UNUSED,
                                   void *data)
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapReparentDataPtr rep = data;

6480
    if (rep->err < 0)
6481
        return 0;
6482 6483 6484 6485 6486 6487 6488

    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;
6489
        return 0;
6490 6491 6492 6493
    }

    if (!snap->sibling)
        rep->last = snap;
6494
    return 0;
6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523
}

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) {
6524
            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)
6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567
                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;
6568
 cleanup:
6569
    virDomainObjEndAPI(&vm);
6570 6571 6572 6573 6574 6575 6576
    return ret;
}

static int
testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                           unsigned int flags)
{
6577
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6578 6579
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
6580 6581
    virObjectEventPtr event = NULL;
    virObjectEventPtr event2 = NULL;
6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644
    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;
6645 6646
    config = virDomainDefCopy(snap->def->dom, privconn->caps,
                              privconn->xmlopt, NULL, true);
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 6672
    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);
6673
                event = virDomainEventLifecycleNewFromObj(vm,
6674 6675
                            VIR_DOMAIN_EVENT_STOPPED,
                            VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
6676
                testObjectEventQueue(privconn, event);
6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687
                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. */
6688
                event = virDomainEventLifecycleNewFromObj(vm,
6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701
                                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;
6702
            event = virDomainEventLifecycleNewFromObj(vm,
6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715
                                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 */
6716
                event2 = virDomainEventLifecycleNewFromObj(vm,
6717 6718 6719 6720 6721
                                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 已提交
6722
            virObjectUnref(event);
6723 6724 6725 6726
            event = NULL;

            if (was_stopped) {
                /* Transition 2 */
6727
                event = virDomainEventLifecycleNewFromObj(vm,
6728 6729 6730 6731
                                VIR_DOMAIN_EVENT_STARTED,
                                VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            } else if (was_running) {
                /* Transition 8 */
6732
                event = virDomainEventLifecycleNewFromObj(vm,
6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744
                                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);
6745
            event = virDomainEventLifecycleNewFromObj(vm,
6746 6747 6748 6749 6750 6751 6752 6753 6754
                                    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;

6755
            testObjectEventQueue(privconn, event);
6756
            event = virDomainEventLifecycleNewFromObj(vm,
6757 6758 6759
                            VIR_DOMAIN_EVENT_STARTED,
                            VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            if (paused) {
6760
                event2 = virDomainEventLifecycleNewFromObj(vm,
6761 6762 6763 6764 6765 6766 6767 6768
                                VIR_DOMAIN_EVENT_SUSPENDED,
                                VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
            }
        }
    }

    vm->current_snapshot = snap;
    ret = 0;
6769
 cleanup:
6770
    if (event) {
6771
        testObjectEventQueue(privconn, event);
6772
        testObjectEventQueue(privconn, event2);
C
Cole Robinson 已提交
6773
    } else {
C
Cédric Bosdonnat 已提交
6774
        virObjectUnref(event2);
6775
    }
6776
    virDomainObjEndAPI(&vm);
6777 6778 6779 6780 6781

    return ret;
}


6782

6783
static virHypervisorDriver testHypervisorDriver = {
6784
    .name = "Test",
6785 6786 6787
    .connectOpen = testConnectOpen, /* 0.1.1 */
    .connectClose = testConnectClose, /* 0.1.1 */
    .connectGetVersion = testConnectGetVersion, /* 0.1.1 */
6788
    .connectGetHostname = testConnectGetHostname, /* 0.6.3 */
6789
    .connectGetMaxVcpus = testConnectGetMaxVcpus, /* 0.3.2 */
6790
    .nodeGetInfo = testNodeGetInfo, /* 0.1.1 */
6791
    .nodeGetCPUStats = testNodeGetCPUStats, /* 2.3.0 */
6792
    .nodeGetFreeMemory = testNodeGetFreeMemory, /* 2.3.0 */
6793
    .nodeGetFreePages = testNodeGetFreePages, /* 2.3.0 */
6794
    .connectGetCapabilities = testConnectGetCapabilities, /* 0.2.1 */
6795
    .connectGetSysinfo = testConnectGetSysinfo, /* 2.3.0 */
6796
    .connectGetType = testConnectGetType, /* 2.3.0 */
6797 6798 6799
    .connectListDomains = testConnectListDomains, /* 0.1.1 */
    .connectNumOfDomains = testConnectNumOfDomains, /* 0.1.1 */
    .connectListAllDomains = testConnectListAllDomains, /* 0.9.13 */
6800
    .domainCreateXML = testDomainCreateXML, /* 0.1.4 */
6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814
    .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 */
6815 6816
    .domainGetState = testDomainGetState, /* 0.9.2 */
    .domainSave = testDomainSave, /* 0.3.2 */
6817
    .domainSaveFlags = testDomainSaveFlags, /* 0.9.4 */
6818
    .domainRestore = testDomainRestore, /* 0.3.2 */
6819
    .domainRestoreFlags = testDomainRestoreFlags, /* 0.9.4 */
6820
    .domainCoreDump = testDomainCoreDump, /* 0.3.2 */
6821
    .domainCoreDumpWithFormat = testDomainCoreDumpWithFormat, /* 1.2.3 */
6822
    .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */
6823 6824 6825 6826
    .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */
    .domainGetVcpusFlags = testDomainGetVcpusFlags, /* 0.8.5 */
    .domainPinVcpu = testDomainPinVcpu, /* 0.7.3 */
    .domainGetVcpus = testDomainGetVcpus, /* 0.7.3 */
6827
    .domainGetVcpuPinInfo = testDomainGetVcpuPinInfo, /* 1.2.18 */
6828 6829
    .domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
    .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
6830 6831
    .connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
    .connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
6832 6833 6834
    .domainCreate = testDomainCreate, /* 0.1.11 */
    .domainCreateWithFlags = testDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = testDomainDefineXML, /* 0.1.11 */
6835
    .domainDefineXMLFlags = testDomainDefineXMLFlags, /* 1.2.12 */
6836
    .domainUndefine = testDomainUndefine, /* 0.1.11 */
6837
    .domainUndefineFlags = testDomainUndefineFlags, /* 0.9.4 */
6838 6839 6840
    .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
    .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
    .domainGetSchedulerType = testDomainGetSchedulerType, /* 0.3.2 */
6841 6842 6843 6844
    .domainGetSchedulerParameters = testDomainGetSchedulerParameters, /* 0.3.2 */
    .domainGetSchedulerParametersFlags = testDomainGetSchedulerParametersFlags, /* 0.9.2 */
    .domainSetSchedulerParameters = testDomainSetSchedulerParameters, /* 0.3.2 */
    .domainSetSchedulerParametersFlags = testDomainSetSchedulerParametersFlags, /* 0.9.2 */
6845 6846 6847
    .domainBlockStats = testDomainBlockStats, /* 0.7.0 */
    .domainInterfaceStats = testDomainInterfaceStats, /* 0.7.0 */
    .nodeGetCellsFreeMemory = testNodeGetCellsFreeMemory, /* 0.4.2 */
6848 6849 6850 6851
    .connectDomainEventRegister = testConnectDomainEventRegister, /* 0.6.0 */
    .connectDomainEventDeregister = testConnectDomainEventDeregister, /* 0.6.0 */
    .connectIsEncrypted = testConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = testConnectIsSecure, /* 0.7.3 */
6852 6853 6854
    .domainIsActive = testDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = testDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = testDomainIsUpdated, /* 0.8.6 */
6855 6856 6857
    .connectDomainEventRegisterAny = testConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = testConnectDomainEventDeregisterAny, /* 0.8.0 */
    .connectIsAlive = testConnectIsAlive, /* 0.9.8 */
6858
    .nodeGetCPUMap = testNodeGetCPUMap, /* 1.0.0 */
6859
    .domainScreenshot = testDomainScreenshot, /* 1.0.5 */
6860 6861
    .domainGetMetadata = testDomainGetMetadata, /* 1.1.3 */
    .domainSetMetadata = testDomainSetMetadata, /* 1.1.3 */
6862
    .connectGetCPUModelNames = testConnectGetCPUModelNames, /* 1.1.3 */
6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879
    .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 */
6880 6881 6882
    .domainSnapshotCreateXML = testDomainSnapshotCreateXML, /* 1.1.4 */
    .domainRevertToSnapshot = testDomainRevertToSnapshot, /* 1.1.4 */
    .domainSnapshotDelete = testDomainSnapshotDelete, /* 1.1.4 */
6883

E
Eric Blake 已提交
6884
    .connectBaselineCPU = testConnectBaselineCPU, /* 1.2.0 */
6885 6886 6887
};

static virNetworkDriver testNetworkDriver = {
6888 6889 6890 6891 6892
    .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 */
6893 6894
    .connectNetworkEventRegisterAny = testConnectNetworkEventRegisterAny, /* 1.2.1 */
    .connectNetworkEventDeregisterAny = testConnectNetworkEventDeregisterAny, /* 1.2.1 */
6895 6896 6897 6898
    .networkLookupByUUID = testNetworkLookupByUUID, /* 0.3.2 */
    .networkLookupByName = testNetworkLookupByName, /* 0.3.2 */
    .networkCreateXML = testNetworkCreateXML, /* 0.3.2 */
    .networkDefineXML = testNetworkDefineXML, /* 0.3.2 */
6899
    .networkUndefine = testNetworkUndefine, /* 0.3.2 */
6900
    .networkUpdate = testNetworkUpdate, /* 0.10.2 */
6901
    .networkCreate = testNetworkCreate, /* 0.3.2 */
6902 6903 6904 6905 6906 6907 6908
    .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 */
6909 6910
};

L
Laine Stump 已提交
6911
static virInterfaceDriver testInterfaceDriver = {
6912 6913 6914 6915 6916 6917
    .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 */
6918 6919 6920 6921 6922 6923
    .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 */
6924 6925 6926
    .interfaceChangeBegin = testInterfaceChangeBegin,   /* 0.9.2 */
    .interfaceChangeCommit = testInterfaceChangeCommit,  /* 0.9.2 */
    .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */
L
Laine Stump 已提交
6927 6928 6929
};


6930
static virStorageDriver testStorageDriver = {
6931 6932 6933 6934 6935 6936
    .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 */
6937 6938
    .connectStoragePoolEventRegisterAny = testConnectStoragePoolEventRegisterAny, /* 2.0.0 */
    .connectStoragePoolEventDeregisterAny = testConnectStoragePoolEventDeregisterAny, /* 2.0.0 */
6939 6940 6941
    .storagePoolLookupByName = testStoragePoolLookupByName, /* 0.5.0 */
    .storagePoolLookupByUUID = testStoragePoolLookupByUUID, /* 0.5.0 */
    .storagePoolLookupByVolume = testStoragePoolLookupByVolume, /* 0.5.0 */
6942 6943
    .storagePoolCreateXML = testStoragePoolCreateXML, /* 0.5.0 */
    .storagePoolDefineXML = testStoragePoolDefineXML, /* 0.5.0 */
6944 6945
    .storagePoolBuild = testStoragePoolBuild, /* 0.5.0 */
    .storagePoolUndefine = testStoragePoolUndefine, /* 0.5.0 */
6946
    .storagePoolCreate = testStoragePoolCreate, /* 0.5.0 */
6947 6948 6949 6950 6951 6952 6953
    .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 */
6954
    .storagePoolNumOfVolumes = testStoragePoolNumOfVolumes, /* 0.5.0 */
6955 6956 6957
    .storagePoolListVolumes = testStoragePoolListVolumes, /* 0.5.0 */
    .storagePoolListAllVolumes = testStoragePoolListAllVolumes, /* 0.10.2 */

6958 6959 6960 6961 6962 6963 6964 6965 6966
    .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 */
6967 6968
    .storagePoolIsActive = testStoragePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = testStoragePoolIsPersistent, /* 0.7.3 */
6969 6970
};

6971
static virNodeDeviceDriver testNodeDeviceDriver = {
6972 6973
    .connectNodeDeviceEventRegisterAny = testConnectNodeDeviceEventRegisterAny, /* 2.2.0 */
    .connectNodeDeviceEventDeregisterAny = testConnectNodeDeviceEventDeregisterAny, /* 2.2.0 */
6974 6975 6976 6977 6978 6979 6980 6981 6982
    .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 */
6983 6984
};

6985 6986 6987 6988 6989 6990 6991 6992
static virConnectDriver testConnectDriver = {
    .hypervisorDriver = &testHypervisorDriver,
    .interfaceDriver = &testInterfaceDriver,
    .networkDriver = &testNetworkDriver,
    .nodeDeviceDriver = &testNodeDeviceDriver,
    .nwfilterDriver = NULL,
    .secretDriver = NULL,
    .storageDriver = &testStorageDriver,
6993 6994
};

6995 6996 6997 6998 6999 7000 7001 7002
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
7003 7004
    return virRegisterConnectDriver(&testConnectDriver,
                                    false);
7005
}