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

24
#include <config.h>
25

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

35

36
#include "virerror.h"
37
#include "datatypes.h"
38
#include "test_driver.h"
39
#include "virbuffer.h"
40
#include "viruuid.h"
41
#include "capabilities.h"
42
#include "configmake.h"
43
#include "viralloc.h"
J
John Ferlan 已提交
44
#include "virnetworkobj.h"
L
Laine Stump 已提交
45
#include "interface_conf.h"
46
#include "domain_conf.h"
47
#include "domain_event.h"
48
#include "network_event.h"
49
#include "snapshot_conf.h"
50
#include "virfdstream.h"
C
Cole Robinson 已提交
51
#include "storage_conf.h"
J
John Ferlan 已提交
52
#include "virstorageobj.h"
53
#include "storage_event.h"
54
#include "node_device_conf.h"
J
John Ferlan 已提交
55
#include "virnodedeviceobj.h"
56
#include "node_device_event.h"
57
#include "virxml.h"
58
#include "virthread.h"
59
#include "virlog.h"
E
Eric Blake 已提交
60
#include "virfile.h"
61
#include "virtypedparam.h"
62
#include "virrandom.h"
63
#include "virstring.h"
64
#include "cpu/cpu.h"
65
#include "virauth.h"
66
#include "viratomic.h"
67
#include "virdomainobjlist.h"
J
John Ferlan 已提交
68
#include "virinterfaceobj.h"
69
#include "virhostcpu.h"
70

71 72
#define VIR_FROM_THIS VIR_FROM_TEST

73 74
VIR_LOG_INIT("test.test_driver");

75

76 77 78 79
#define MAX_CPUS 128

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

#define MAX_CELLS 128
88

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

96
struct _testDriver {
97
    virMutex lock;
98

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

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

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

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

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

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

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

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

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

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

    VIR_FREE(driver);
}
165

166

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

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

177 178 179 180 181 182
static void testObjectEventQueue(testDriverPtr driver,
                                 virObjectEventPtr event)
{
    virObjectEventStateQueue(driver->eventState, event);
}

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

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

    unsigned int num_snap_nodes;
    xmlNodePtr *snap_nodes;
194 195 196 197 198 199
};

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

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

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

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

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

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

295 296 297
    *data = nsdata;
    return 0;

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

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

314
    if ((caps = virCapabilitiesNew(VIR_ARCH_I686, false, false)) == NULL)
315
        goto error;
316

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

322 323
    virCapabilitiesHostInitIOMMU(caps);

324
    if (VIR_ALLOC_N(caps->host.pagesSize, 4) < 0)
325 326 327
        goto error;

    caps->host.pagesSize[caps->host.nPagesSize++] = 4;
328
    caps->host.pagesSize[caps->host.nPagesSize++] = 8;
329
    caps->host.pagesSize[caps->host.nPagesSize++] = 2048;
330
    caps->host.pagesSize[caps->host.nPagesSize++] = 1024 * 1024;
331

332
    for (i = 0; i < privconn->numCells; i++) {
333
        virCapsHostNUMACellCPUPtr cpu_cells;
334
        virCapsHostNUMACellPageInfoPtr pages;
335
        size_t nPages = caps->host.nPagesSize - 1;
336

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

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

346 347 348 349 350 351 352
        if (i == 1)
            pages[0].size = caps->host.pagesSize[1];
        else
            pages[0].size = caps->host.pagesSize[0];

        for (j = 1; j < nPages; j++)
            pages[j].size = caps->host.pagesSize[j + 1];
353 354

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

356
        if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].mem,
357
                                           privconn->cells[i].numCpus,
358
                                           cpu_cells, 0, NULL, nPages, pages) < 0)
359
            goto error;
360 361
    }

362
    for (i = 0; i < ARRAY_CARDINALITY(guest_types); i++) {
363 364
        if ((guest = virCapabilitiesAddGuest(caps,
                                             guest_types[i],
365
                                             VIR_ARCH_I686,
366 367 368 369
                                             TEST_EMULATOR,
                                             NULL,
                                             0,
                                             NULL)) == NULL)
370
            goto error;
371

372
        if (virCapabilitiesAddGuestDomain(guest,
373
                                          VIR_DOMAIN_VIRT_TEST,
374 375 376 377
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
378
            goto error;
379

380
        if (virCapabilitiesAddGuestFeature(guest, "pae", true, true) == NULL)
381
            goto error;
382
        if (virCapabilitiesAddGuestFeature(guest, "nonpae", true, true) == NULL)
383
            goto error;
384 385
    }

386 387
    caps->host.nsecModels = 1;
    if (VIR_ALLOC_N(caps->host.secModels, caps->host.nsecModels) < 0)
388
        goto error;
389 390
    if (VIR_STRDUP(caps->host.secModels[0].model, "testSecurity") < 0)
        goto error;
391

392 393
    if (VIR_STRDUP(caps->host.secModels[0].doi, "") < 0)
        goto error;
394

395
    return caps;
396

397
 error:
398
    virObjectUnref(caps);
399
    return NULL;
400 401
}

402

403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
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;
    }

421
    if (!(ret->xmlopt = virDomainXMLOptionNew(NULL, NULL, &ns, NULL, NULL)) ||
422
        !(ret->eventState = virObjectEventStateNew()) ||
423
        !(ret->ifaces = virInterfaceObjListNew()) ||
424
        !(ret->domains = virDomainObjListNew()) ||
425
        !(ret->networks = virNetworkObjListNew()) ||
426 427
        !(ret->devs = virNodeDeviceObjListNew()) ||
        !(ret->pools = virStoragePoolObjListNew()))
428 429
        goto error;

430
    virAtomicIntSet(&ret->nextDomID, 1);
431 432 433 434 435 436 437 438 439

    return ret;

 error:
    testDriverFree(ret);
    return NULL;
}


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

C
Cole Robinson 已提交
548

549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
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";

572
static const unsigned long long defaultPoolCap = (100 * 1024 * 1024 * 1024ull);
573
static const unsigned long long defaultPoolAlloc;
C
Cole Robinson 已提交
574

575
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr obj);
576
static int testNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
577

578 579 580 581
static virDomainObjPtr
testDomObjFromDomain(virDomainPtr domain)
{
    virDomainObjPtr vm;
582
    testDriverPtr driver = domain->conn->privateData;
583 584
    char uuidstr[VIR_UUID_STRING_BUFLEN];

585
    vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
586 587 588 589 590 591 592 593 594 595
    if (!vm) {
        virUUIDFormat(domain->uuid, uuidstr);
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching uuid '%s' (%s)"),
                       uuidstr, domain->name);
    }

    return vm;
}

596
static char *
597 598
testDomainGenerateIfname(virDomainDefPtr domdef)
{
599
    int maxif = 1024;
600
    int ifctr;
601 602

    for (ifctr = 0; ifctr < maxif; ++ifctr) {
M
Michal Privoznik 已提交
603
        virDomainNetDefPtr net = NULL;
604 605
        char *ifname;

606
        if (virAsprintf(&ifname, "testnet%d", ifctr) < 0)
607 608 609
            return NULL;

        /* Generate network interface names */
M
Michal Privoznik 已提交
610
        if (!(net = virDomainNetFindByName(domdef, ifname)))
611
            return ifname;
612
        VIR_FREE(ifname);
613 614
    }

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

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

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

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

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

637
    return 0;
638 639
}

640

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

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

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

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

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

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

678

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

928
        if (testParseDomainSnapshots(privconn, obj, file, ctxt) < 0)
929 930
            goto error;

931
        nsdata = def->namespaceData;
932
        obj->persistent = !nsdata->transient;
C
Cole Robinson 已提交
933
        obj->hasManagedSave = nsdata->hasManagedSave;
934 935 936

        if (nsdata->runstate != VIR_DOMAIN_SHUTOFF) {
            if (testDomainStartState(privconn, obj,
937
                                     VIR_DOMAIN_RUNNING_BOOTED) < 0)
938 939 940
                goto error;
        } else {
            testDomainShutdownState(NULL, obj, 0);
941
        }
942
        virDomainObjSetState(obj, nsdata->runstate, 0);
943

944
        virDomainObjEndAPI(&obj);
945
    }
946

947
    ret = 0;
948
 error:
949
    virDomainObjEndAPI(&obj);
950 951 952 953
    VIR_FREE(nodes);
    return ret;
}

954

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

    num = virXPathNodeSet("/node/network", ctxt, &nodes);
966
    if (num < 0)
967
        goto error;
968 969

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

C
Cole Robinson 已提交
975 976 977
        def = virNetworkDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
978

979
        if (!(obj = virNetworkObjAssignDef(privconn->networks, def, 0))) {
980 981
            virNetworkDefFree(def);
            goto error;
982
        }
983

984
        virNetworkObjSetActive(obj, true);
985
        virNetworkObjEndAPI(&obj);
986
    }
987

988
    ret = 0;
989
 error:
990 991 992 993
    VIR_FREE(nodes);
    return ret;
}

994

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

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

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

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

1020
        if (!(obj = virInterfaceObjListAssignDef(privconn->ifaces, def))) {
L
Laine Stump 已提交
1021 1022 1023
            virInterfaceDefFree(def);
            goto error;
        }
1024

1025
        virInterfaceObjSetActive(obj, true);
1026
        virInterfaceObjEndAPI(&obj);
1027 1028 1029
    }

    ret = 0;
1030
 error:
1031 1032 1033 1034
    VIR_FREE(nodes);
    return ret;
}

1035

1036
static int
C
Cole Robinson 已提交
1037
testOpenVolumesForPool(const char *file,
1038
                       xmlXPathContextPtr ctxt,
1039 1040
                       virStoragePoolObjPtr obj,
                       int objidx)
1041
{
1042
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(obj);
1043 1044 1045 1046
    char *vol_xpath;
    size_t i;
    int num, ret = -1;
    xmlNodePtr *nodes = NULL;
1047
    virStorageVolDefPtr volDef = NULL;
1048 1049

    /* Find storage volumes */
1050
    if (virAsprintf(&vol_xpath, "/node/pool[%d]/volume", objidx) < 0)
1051 1052 1053 1054
        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
        if (!(volDef = virStorageVolDefParseNode(def, ctxt->doc, node, 0)))
C
Cole Robinson 已提交
1065
            goto error;
1066

1067 1068
        if (!volDef->target.path) {
            if (virAsprintf(&volDef->target.path, "%s/%s",
1069
                            def->target.path, volDef->name) < 0)
1070 1071 1072
                goto error;
        }

1073
        if (!volDef->key && VIR_STRDUP(volDef->key, volDef->target.path) < 0)
1074
            goto error;
1075

1076
        if (virStoragePoolObjAddVol(obj, volDef) < 0)
1077
            goto error;
1078

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

1084
    ret = 0;
1085
 error:
1086
    virStorageVolDefFree(volDef);
1087 1088 1089 1090
    VIR_FREE(nodes);
    return ret;
}

1091

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

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

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

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

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

1122
        if (testStoragePoolObjSetDefaults(obj) == -1) {
1123
            virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
1124
            goto error;
1125
        }
1126
        virStoragePoolObjSetActive(obj, true);
1127 1128

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

1134
        virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
1135 1136
    }

1137
    ret = 0;
1138
 error:
1139 1140 1141 1142
    VIR_FREE(nodes);
    return ret;
}

1143

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

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

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

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

1169
        if (!(obj = virNodeDeviceObjListAssignDef(privconn->devs, def))) {
1170 1171 1172
            virNodeDeviceDefFree(def);
            goto error;
        }
1173

1174
        virNodeDeviceObjEndAPI(&obj);
1175 1176 1177
    }

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

1183
static int
1184
testParseAuthUsers(testDriverPtr privconn,
1185 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
                   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;
1218
 error:
1219 1220 1221
    VIR_FREE(nodes);
    return ret;
}
1222

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

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

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

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

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

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

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

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

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

1285
    return VIR_DRV_OPEN_SUCCESS;
1286 1287

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

1295 1296 1297 1298 1299 1300
/* 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)
{
1301
    int ret = VIR_DRV_OPEN_ERROR;
1302
    testDriverPtr privconn = NULL;
1303 1304
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
1305
    size_t i;
1306 1307 1308

    virMutexLock(&defaultLock);
    if (defaultConnections++) {
1309
        conn->privateData = defaultPrivconn;
1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322
        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
        goto error;

1349
    defaultPrivconn = privconn;
1350 1351 1352
    ret = VIR_DRV_OPEN_SUCCESS;
 cleanup:
    virMutexUnlock(&defaultLock);
1353 1354
    xmlXPathFreeContext(ctxt);
    xmlFreeDoc(doc);
1355
    return ret;
1356 1357 1358 1359 1360

 error:
    testDriverFree(privconn);
    conn->privateData = NULL;
    defaultConnections--;
1361
    goto cleanup;
1362 1363
}

1364 1365 1366 1367
static int
testConnectAuthenticate(virConnectPtr conn,
                        virConnectAuthPtr auth)
{
1368
    testDriverPtr privconn = conn->privateData;
1369 1370 1371 1372
    int ret = -1;
    ssize_t i;
    char *username = NULL, *password = NULL;

1373 1374 1375
    testDriverLock(privconn);
    if (privconn->numAuths == 0) {
        testDriverUnlock(privconn);
1376
        return 0;
1377
    }
1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395

    /* 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
    testDriverUnlock(privconn);
1418 1419 1420 1421
    VIR_FREE(username);
    VIR_FREE(password);
    return ret;
}
1422

1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452

static void
testDriverCloseInternal(testDriverPtr driver)
{
    bool dflt = false;

    if (driver == defaultPrivconn) {
        dflt = true;
        virMutexLock(&defaultLock);
        if (--defaultConnections) {
            virMutexUnlock(&defaultLock);
            return;
        }
    }

    testDriverLock(driver);
    testDriverFree(driver);

    if (dflt) {
        defaultPrivconn = NULL;
        virMutexUnlock(&defaultLock);
    }
}


static virDrvOpenStatus
testConnectOpen(virConnectPtr conn,
                virConnectAuthPtr auth,
                virConfPtr conf ATTRIBUTE_UNUSED,
                unsigned int flags)
1453
{
1454
    int ret;
1455

E
Eric Blake 已提交
1456 1457
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

1458 1459
    if (conn->uri->path[0] == '\0' ||
        (conn->uri->path[0] == '/' && conn->uri->path[1] == '\0')) {
1460 1461
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("testOpen: supply a path or use test:///default"));
1462 1463
        return VIR_DRV_OPEN_ERROR;
    }
1464

1465
    if (STREQ(conn->uri->path, "/default"))
1466 1467
        ret = testOpenDefault(conn);
    else
1468
        ret = testOpenFromFile(conn,
1469
                               conn->uri->path);
1470

1471 1472 1473
    if (ret != VIR_DRV_OPEN_SUCCESS)
        return ret;

1474
    /* Fake authentication. */
1475 1476 1477
    if (testConnectAuthenticate(conn, auth) < 0) {
        testDriverCloseInternal(conn->privateData);
        conn->privateData = NULL;
1478
        return VIR_DRV_OPEN_ERROR;
1479
    }
1480

1481
    return VIR_DRV_OPEN_SUCCESS;
1482 1483
}

1484

1485 1486 1487 1488
static int
testConnectClose(virConnectPtr conn)
{
    testDriverCloseInternal(conn->privateData);
1489
    conn->privateData = NULL;
1490
    return 0;
1491 1492
}

1493

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

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


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

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

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

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

1528 1529 1530 1531 1532 1533
static char *
testConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED,
                       const char **xmlCPUs,
                       unsigned int ncpus,
                       unsigned int flags)
{
J
Jiri Denemark 已提交
1534 1535 1536
    virCPUDefPtr *cpus = NULL;
    virCPUDefPtr cpu = NULL;
    char *cpustr = NULL;
1537 1538 1539

    virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, NULL);

J
Jiri Denemark 已提交
1540 1541 1542
    if (!(cpus = virCPUDefListParse(xmlCPUs, ncpus, VIR_CPU_TYPE_HOST)))
        goto cleanup;

1543
    if (!(cpu = virCPUBaseline(VIR_ARCH_NONE, cpus, ncpus, NULL, NULL, false)))
J
Jiri Denemark 已提交
1544 1545 1546 1547 1548 1549
        goto cleanup;

    if ((flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) &&
        virCPUExpandFeatures(cpus[0]->arch, cpu) < 0)
        goto cleanup;

1550
    cpustr = virCPUDefFormat(cpu, NULL);
J
Jiri Denemark 已提交
1551 1552 1553 1554

 cleanup:
    virCPUDefListFree(cpus);
    virCPUDefFree(cpu);
1555

J
Jiri Denemark 已提交
1556
    return cpustr;
1557 1558
}

1559 1560
static int testNodeGetInfo(virConnectPtr conn,
                           virNodeInfoPtr info)
1561
{
1562
    testDriverPtr privconn = conn->privateData;
1563
    testDriverLock(privconn);
1564
    memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo));
1565
    testDriverUnlock(privconn);
1566
    return 0;
1567 1568
}

1569
static char *testConnectGetCapabilities(virConnectPtr conn)
1570
{
1571
    testDriverPtr privconn = conn->privateData;
1572
    char *xml;
1573
    testDriverLock(privconn);
1574
    xml = virCapabilitiesFormatXML(privconn->caps);
1575
    testDriverUnlock(privconn);
1576
    return xml;
1577 1578
}

1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598
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;
}

1599 1600 1601 1602 1603 1604
static const char *
testConnectGetType(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return "TEST";
}

1605
static int testConnectNumOfDomains(virConnectPtr conn)
1606
{
1607
    testDriverPtr privconn = conn->privateData;
1608
    int count;
1609

1610
    testDriverLock(privconn);
1611
    count = virDomainObjListNumOfDomains(privconn->domains, true, NULL, NULL);
1612
    testDriverUnlock(privconn);
1613

1614
    return count;
1615 1616
}

1617 1618 1619
static int testDomainIsActive(virDomainPtr dom)
{
    virDomainObjPtr obj;
1620
    int ret;
1621

1622 1623
    if (!(obj = testDomObjFromDomain(dom)))
        return -1;
1624

1625 1626
    ret = virDomainObjIsActive(obj);
    virDomainObjEndAPI(&obj);
1627 1628 1629 1630 1631 1632
    return ret;
}

static int testDomainIsPersistent(virDomainPtr dom)
{
    virDomainObjPtr obj;
1633 1634 1635 1636
    int ret;

    if (!(obj = testDomObjFromDomain(dom)))
        return -1;
1637 1638 1639

    ret = obj->persistent;

1640
    virDomainObjEndAPI(&obj);
1641 1642 1643
    return ret;
}

1644 1645 1646 1647 1648
static int testDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
{
    return 0;
}

1649
static virDomainPtr
1650
testDomainCreateXML(virConnectPtr conn, const char *xml,
1651
                      unsigned int flags)
1652
{
1653
    testDriverPtr privconn = conn->privateData;
1654
    virDomainPtr ret = NULL;
1655
    virDomainDefPtr def;
1656
    virDomainObjPtr dom = NULL;
1657
    virObjectEventPtr event = NULL;
1658
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
1659

1660 1661 1662
    virCheckFlags(VIR_DOMAIN_START_VALIDATE, NULL);

    if (flags & VIR_DOMAIN_START_VALIDATE)
1663
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
1664

1665
    testDriverLock(privconn);
1666
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
1667
                                       NULL, parse_flags)) == NULL)
1668
        goto cleanup;
1669

1670
    if (testDomainGenerateIfnames(def) < 0)
1671
        goto cleanup;
1672
    if (!(dom = virDomainObjListAdd(privconn->domains,
1673
                                    def,
1674
                                    privconn->xmlopt,
1675
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
1676 1677
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
1678 1679
        goto cleanup;
    def = NULL;
1680

1681
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_BOOTED) < 0) {
1682
        if (!dom->persistent)
1683
            virDomainObjListRemove(privconn->domains, dom);
1684
        goto cleanup;
1685
    }
1686

1687
    event = virDomainEventLifecycleNewFromObj(dom,
1688 1689 1690
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);

1691
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
1692

1693
 cleanup:
1694
    virDomainObjEndAPI(&dom);
1695
    testObjectEventQueue(privconn, event);
1696
    virDomainDefFree(def);
1697
    testDriverUnlock(privconn);
1698
    return ret;
1699 1700 1701
}


1702
static virDomainPtr testDomainLookupByID(virConnectPtr conn,
1703
                                         int id)
1704
{
1705
    testDriverPtr privconn = conn->privateData;
1706 1707
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1708

1709
    if (!(dom = virDomainObjListFindByID(privconn->domains, id))) {
1710
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1711
        return NULL;
1712 1713
    }

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

1716
    virDomainObjEndAPI(&dom);
1717
    return ret;
1718 1719
}

1720
static virDomainPtr testDomainLookupByUUID(virConnectPtr conn,
1721
                                           const unsigned char *uuid)
1722
{
1723
    testDriverPtr privconn = conn->privateData;
1724
    virDomainPtr ret = NULL;
1725
    virDomainObjPtr dom;
1726

1727
    if (!(dom = virDomainObjListFindByUUID(privconn->domains, uuid))) {
1728
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1729
        return NULL;
1730
    }
1731

1732
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
1733

1734
    virDomainObjEndAPI(&dom);
1735
    return ret;
1736 1737
}

1738
static virDomainPtr testDomainLookupByName(virConnectPtr conn,
1739
                                           const char *name)
1740
{
1741
    testDriverPtr privconn = conn->privateData;
1742 1743
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1744

1745
    if (!(dom = virDomainObjListFindByName(privconn->domains, name))) {
1746
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1747
        goto cleanup;
1748
    }
1749

1750
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
1751

1752
 cleanup:
1753
    virDomainObjEndAPI(&dom);
1754
    return ret;
1755 1756
}

1757 1758 1759
static int testConnectListDomains(virConnectPtr conn,
                                  int *ids,
                                  int maxids)
1760
{
1761
    testDriverPtr privconn = conn->privateData;
1762

1763 1764
    return virDomainObjListGetActiveIDs(privconn->domains, ids, maxids,
                                        NULL, NULL);
1765 1766
}

1767 1768
static int testDomainDestroyFlags(virDomainPtr domain,
                                  unsigned int flags)
1769
{
1770
    testDriverPtr privconn = domain->conn->privateData;
1771
    virDomainObjPtr privdom;
1772
    virObjectEventPtr event = NULL;
1773
    int ret = -1;
1774

1775 1776
    virCheckFlags(VIR_DOMAIN_DESTROY_GRACEFUL, -1);

1777
    if (!(privdom = testDomObjFromDomain(domain)))
1778
        goto cleanup;
1779

1780
    if (virDomainObjCheckActive(privdom) < 0)
1781 1782
        goto cleanup;

J
Jiri Denemark 已提交
1783
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_DESTROYED);
1784
    event = virDomainEventLifecycleNewFromObj(privdom,
1785 1786
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
1787

1788
    if (!privdom->persistent)
1789
        virDomainObjListRemove(privconn->domains, privdom);
1790 1791

    ret = 0;
1792
 cleanup:
1793
    virDomainObjEndAPI(&privdom);
1794
    testObjectEventQueue(privconn, event);
1795
    return ret;
1796 1797
}

1798 1799 1800 1801 1802
static int testDomainDestroy(virDomainPtr domain)
{
    return testDomainDestroyFlags(domain, 0);
}

1803
static int testDomainResume(virDomainPtr domain)
1804
{
1805
    testDriverPtr privconn = domain->conn->privateData;
1806
    virDomainObjPtr privdom;
1807
    virObjectEventPtr event = NULL;
1808
    int ret = -1;
1809

1810 1811
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1812

J
Jiri Denemark 已提交
1813
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_PAUSED) {
1814 1815
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"),
                       domain->name);
1816
        goto cleanup;
1817
    }
1818

J
Jiri Denemark 已提交
1819 1820
    virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                         VIR_DOMAIN_RUNNING_UNPAUSED);
1821
    event = virDomainEventLifecycleNewFromObj(privdom,
1822 1823
                                     VIR_DOMAIN_EVENT_RESUMED,
                                     VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
1824 1825
    ret = 0;

1826
 cleanup:
1827
    virDomainObjEndAPI(&privdom);
1828
    testObjectEventQueue(privconn, event);
1829
    return ret;
1830 1831
}

1832
static int testDomainSuspend(virDomainPtr domain)
1833
{
1834
    testDriverPtr privconn = domain->conn->privateData;
1835
    virDomainObjPtr privdom;
1836
    virObjectEventPtr event = NULL;
1837
    int ret = -1;
J
Jiri Denemark 已提交
1838
    int state;
1839

1840 1841
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1842

J
Jiri Denemark 已提交
1843 1844
    state = virDomainObjGetState(privdom, NULL);
    if (state == VIR_DOMAIN_SHUTOFF || state == VIR_DOMAIN_PAUSED) {
1845 1846
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"),
                       domain->name);
1847
        goto cleanup;
1848
    }
1849

J
Jiri Denemark 已提交
1850
    virDomainObjSetState(privdom, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
1851
    event = virDomainEventLifecycleNewFromObj(privdom,
1852 1853
                                     VIR_DOMAIN_EVENT_SUSPENDED,
                                     VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
1854 1855
    ret = 0;

1856
 cleanup:
1857
    virDomainObjEndAPI(&privdom);
1858
    testObjectEventQueue(privconn, event);
1859
    return ret;
1860 1861
}

1862
static int testDomainShutdownFlags(virDomainPtr domain,
1863
                                   unsigned int flags)
1864
{
1865
    testDriverPtr privconn = domain->conn->privateData;
1866
    virDomainObjPtr privdom;
1867
    virObjectEventPtr event = NULL;
1868
    int ret = -1;
1869

1870 1871
    virCheckFlags(0, -1);

1872

1873
    if (!(privdom = testDomObjFromDomain(domain)))
1874
        goto cleanup;
1875

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

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

1887
    if (!privdom->persistent)
1888
        virDomainObjListRemove(privconn->domains, privdom);
1889

1890
    ret = 0;
1891
 cleanup:
1892
    virDomainObjEndAPI(&privdom);
1893
    testObjectEventQueue(privconn, event);
1894
    return ret;
1895 1896
}

1897
static int testDomainShutdown(virDomainPtr domain)
1898
{
1899
    return testDomainShutdownFlags(domain, 0);
1900 1901
}

1902
/* Similar behaviour as shutdown */
1903
static int testDomainReboot(virDomainPtr domain,
1904
                            unsigned int action ATTRIBUTE_UNUSED)
1905
{
1906
    testDriverPtr privconn = domain->conn->privateData;
1907
    virDomainObjPtr privdom;
1908
    virObjectEventPtr event = NULL;
1909
    int ret = -1;
1910 1911


1912
    if (!(privdom = testDomObjFromDomain(domain)))
1913
        goto cleanup;
1914

1915
    if (virDomainObjCheckActive(privdom) < 0)
1916 1917
        goto cleanup;

J
Jiri Denemark 已提交
1918 1919 1920
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTDOWN,
                         VIR_DOMAIN_SHUTDOWN_USER);

1921
    switch (privdom->def->onReboot) {
1922
    case VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY:
J
Jiri Denemark 已提交
1923 1924
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1925 1926
        break;

1927
    case VIR_DOMAIN_LIFECYCLE_ACTION_RESTART:
J
Jiri Denemark 已提交
1928 1929
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
1930 1931
        break;

1932
    case VIR_DOMAIN_LIFECYCLE_ACTION_PRESERVE:
J
Jiri Denemark 已提交
1933 1934
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1935 1936
        break;

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

1942
    default:
J
Jiri Denemark 已提交
1943 1944
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1945 1946
        break;
    }
1947

J
Jiri Denemark 已提交
1948 1949
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1950
        event = virDomainEventLifecycleNewFromObj(privdom,
1951 1952
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1953

1954
        if (!privdom->persistent)
1955
            virDomainObjListRemove(privconn->domains, privdom);
1956 1957
    }

1958
    ret = 0;
1959
 cleanup:
1960
    virDomainObjEndAPI(&privdom);
1961
    testObjectEventQueue(privconn, event);
1962
    return ret;
1963 1964
}

1965
static int testDomainGetInfo(virDomainPtr domain,
1966
                             virDomainInfoPtr info)
1967
{
1968
    struct timeval tv;
1969
    virDomainObjPtr privdom;
1970
    int ret = -1;
1971

1972 1973
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1974 1975

    if (gettimeofday(&tv, NULL) < 0) {
1976 1977
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("getting time of day"));
1978
        goto cleanup;
1979 1980
    }

J
Jiri Denemark 已提交
1981
    info->state = virDomainObjGetState(privdom, NULL);
1982
    info->memory = privdom->def->mem.cur_balloon;
1983
    info->maxMem = virDomainDefGetMemoryTotal(privdom->def);
1984
    info->nrVirtCpu = virDomainDefGetVcpus(privdom->def);
1985
    info->cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
1986 1987
    ret = 0;

1988
 cleanup:
1989
    virDomainObjEndAPI(&privdom);
1990
    return ret;
1991 1992
}

1993 1994 1995 1996 1997 1998 1999 2000 2001 2002
static int
testDomainGetState(virDomainPtr domain,
                   int *state,
                   int *reason,
                   unsigned int flags)
{
    virDomainObjPtr privdom;

    virCheckFlags(0, -1);

2003 2004
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2005

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

2008
    virDomainObjEndAPI(&privdom);
2009 2010

    return 0;
2011 2012
}

2013 2014
#define TEST_SAVE_MAGIC "TestGuestMagic"

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

2027 2028
    virCheckFlags(0, -1);
    if (dxml) {
2029 2030
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
2031 2032 2033
        return -1;
    }

2034

2035
    if (!(privdom = testDomObjFromDomain(domain)))
2036
        goto cleanup;
2037

2038
    if (virDomainObjCheckActive(privdom) < 0)
2039 2040
        goto cleanup;

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

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

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

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

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

2090
    if (!privdom->persistent)
2091
        virDomainObjListRemove(privconn->domains, privdom);
2092

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

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

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

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

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

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

2192
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_RESTORED) < 0) {
2193
        if (!dom->persistent)
2194
            virDomainObjListRemove(privconn->domains, dom);
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
    virDomainObjEndAPI(&dom);
2208
    testObjectEventQueue(privconn, event);
2209
    return ret;
2210 2211
}

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

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

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

2232

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

2236
    if (virDomainObjCheckActive(privdom) < 0)
2237 2238
        goto cleanup;

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

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

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

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

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

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)
{
2296 2297 2298
    char *ret;

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

2302 2303 2304

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2450 2451
    ret = 0;

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

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

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

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

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

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

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

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

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

    virBitmapSetAll(allcpumap);

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

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

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

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

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

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

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

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

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

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

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

2556 2557
    def = privdom->def;

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

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

2572 2573 2574
    virBitmapFree(vcpuinfo->cpumask);

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

    ret = 0;
2578

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

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

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

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

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

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

2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625
static int
testDomainRenameCallback(virDomainObjPtr privdom,
                         const char *new_name,
                         unsigned int flags,
                         void *opaque)
{
    testDriverPtr driver = opaque;
    virObjectEventPtr event_new = NULL;
    virObjectEventPtr event_old = NULL;
    int ret = -1;
    char *new_dom_name = NULL;
    char *old_dom_name = NULL;

    virCheckFlags(0, -1);

2626 2627 2628 2629 2630 2631
    if (strchr(new_name, '/')) {
        virReportError(VIR_ERR_XML_ERROR,
                       _("name %s cannot contain '/'"), new_name);
        return -1;
    }

2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700
    if (VIR_STRDUP(new_dom_name, new_name) < 0)
        goto cleanup;

    event_old = virDomainEventLifecycleNewFromObj(privdom,
                                                  VIR_DOMAIN_EVENT_UNDEFINED,
                                                  VIR_DOMAIN_EVENT_UNDEFINED_RENAMED);

    /* Switch name in domain definition. */
    old_dom_name = privdom->def->name;
    privdom->def->name = new_dom_name;
    new_dom_name = NULL;

    event_new = virDomainEventLifecycleNewFromObj(privdom,
                                                  VIR_DOMAIN_EVENT_DEFINED,
                                                  VIR_DOMAIN_EVENT_DEFINED_RENAMED);
    ret = 0;

 cleanup:
    VIR_FREE(old_dom_name);
    VIR_FREE(new_dom_name);
    testObjectEventQueue(driver, event_old);
    testObjectEventQueue(driver, event_new);
    return ret;
}

static int
testDomainRename(virDomainPtr dom,
                 const char *new_name,
                 unsigned int flags)
{
    testDriverPtr driver = dom->conn->privateData;
    virDomainObjPtr privdom = NULL;
    int ret = -1;

    virCheckFlags(0, ret);

    if (!(privdom = testDomObjFromDomain(dom)))
        goto cleanup;

    if (virDomainObjIsActive(privdom)) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot rename active domain"));
        goto cleanup;
    }

    if (!privdom->persistent) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot rename a transient domain"));
        goto cleanup;
    }

    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_SHUTOFF) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain has to be shutoff before renaming"));
        goto cleanup;
    }

    if (virDomainObjListRename(driver->domains, privdom, new_name, flags,
                               testDomainRenameCallback, driver) < 0)
        goto cleanup;

    /* Success, domain has been renamed. */
    ret = 0;

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

2701
static char *testDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
2702
{
2703
    testDriverPtr privconn = domain->conn->privateData;
2704
    virDomainDefPtr def;
2705
    virDomainObjPtr privdom;
2706 2707
    char *ret = NULL;

2708 2709
    /* Flags checked by virDomainDefFormat */

2710 2711
    if (!(privdom = testDomObjFromDomain(domain)))
        return NULL;
2712

2713 2714
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
2715

2716 2717
    ret = virDomainDefFormat(def, privconn->caps,
                             virDomainDefFormatConvertXMLFlags(flags));
2718

2719
    virDomainObjEndAPI(&privdom);
2720
    return ret;
2721
}
2722

2723 2724
static int testConnectNumOfDefinedDomains(virConnectPtr conn)
{
2725
    testDriverPtr privconn = conn->privateData;
2726

2727
    return virDomainObjListNumOfDomains(privconn->domains, false, NULL, NULL);
2728 2729
}

2730 2731
static int testConnectListDefinedDomains(virConnectPtr conn,
                                         char **const names,
2732 2733
                                         int maxnames)
{
2734

2735
    testDriverPtr privconn = conn->privateData;
2736 2737

    memset(names, 0, sizeof(*names)*maxnames);
2738 2739
    return virDomainObjListGetInactiveNames(privconn->domains, names, maxnames,
                                            NULL, NULL);
2740 2741
}

2742 2743 2744
static virDomainPtr testDomainDefineXMLFlags(virConnectPtr conn,
                                             const char *xml,
                                             unsigned int flags)
2745
{
2746
    testDriverPtr privconn = conn->privateData;
2747
    virDomainPtr ret = NULL;
2748
    virDomainDefPtr def;
2749
    virDomainObjPtr dom = NULL;
2750
    virObjectEventPtr event = NULL;
2751
    virDomainDefPtr oldDef = NULL;
2752 2753 2754
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;

    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
2755

2756
    if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
2757
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
2758

2759
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
2760
                                       NULL, parse_flags)) == NULL)
2761
        goto cleanup;
2762

2763 2764 2765
    if (virXMLCheckIllegalChars("name", def->name, "\n") < 0)
        goto cleanup;

2766
    if (testDomainGenerateIfnames(def) < 0)
2767
        goto cleanup;
2768
    if (!(dom = virDomainObjListAdd(privconn->domains,
2769
                                    def,
2770
                                    privconn->xmlopt,
2771 2772
                                    0,
                                    &oldDef)))
2773
        goto cleanup;
2774
    def = NULL;
2775
    dom->persistent = 1;
2776

2777
    event = virDomainEventLifecycleNewFromObj(dom,
2778
                                     VIR_DOMAIN_EVENT_DEFINED,
2779
                                     !oldDef ?
2780 2781
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
2782

2783
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
2784

2785
 cleanup:
2786
    virDomainDefFree(def);
2787
    virDomainDefFree(oldDef);
2788
    virDomainObjEndAPI(&dom);
2789
    testObjectEventQueue(privconn, event);
2790
    return ret;
2791 2792
}

2793 2794 2795 2796 2797 2798
static virDomainPtr
testDomainDefineXML(virConnectPtr conn, const char *xml)
{
    return testDomainDefineXMLFlags(conn, xml, 0);
}

2799 2800 2801 2802 2803 2804
static char *testDomainGetMetadata(virDomainPtr dom,
                                   int type,
                                   const char *uri,
                                   unsigned int flags)
{
    virDomainObjPtr privdom;
2805
    char *ret;
2806 2807 2808 2809

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, NULL);

2810 2811
    if (!(privdom = testDomObjFromDomain(dom)))
        return NULL;
2812

2813
    ret = virDomainObjGetMetadata(privdom, type, uri, flags);
2814

2815
    virDomainObjEndAPI(&privdom);
2816 2817 2818 2819 2820 2821 2822 2823 2824 2825
    return ret;
}

static int testDomainSetMetadata(virDomainPtr dom,
                                 int type,
                                 const char *metadata,
                                 const char *key,
                                 const char *uri,
                                 unsigned int flags)
{
2826
    testDriverPtr privconn = dom->conn->privateData;
2827
    virDomainObjPtr privdom;
2828
    int ret;
2829 2830 2831 2832

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

2833 2834
    if (!(privdom = testDomObjFromDomain(dom)))
        return -1;
2835 2836 2837

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

2840 2841 2842 2843 2844 2845
    if (ret == 0) {
        virObjectEventPtr ev = NULL;
        ev = virDomainEventMetadataChangeNewFromObj(privdom, type, uri);
        testObjectEventQueue(privconn, ev);
    }

2846
    virDomainObjEndAPI(&privdom);
2847 2848 2849 2850
    return ret;
}


2851 2852
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
2853 2854
                                      int startCell, int maxCells)
{
2855
    testDriverPtr privconn = conn->privateData;
2856 2857
    int cell;
    size_t i;
2858
    int ret = -1;
2859

2860
    testDriverLock(privconn);
2861
    if (startCell >= privconn->numCells) {
2862 2863
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("Range exceeds available cells"));
2864
        goto cleanup;
2865 2866
    }

2867 2868 2869 2870
    for (cell = startCell, i = 0;
         (cell < privconn->numCells && i < maxCells);
         ++cell, ++i) {
        freemems[i] = privconn->cells[cell].mem;
2871
    }
2872
    ret = i;
2873

2874
 cleanup:
2875
    testDriverUnlock(privconn);
2876
    return ret;
2877 2878
}

2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924
#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;
}
2925

2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941
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;
}

2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965
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;
}

2966 2967
static int testDomainCreateWithFlags(virDomainPtr domain, unsigned int flags)
{
2968
    testDriverPtr privconn = domain->conn->privateData;
2969
    virDomainObjPtr privdom;
2970
    virObjectEventPtr event = NULL;
2971
    int ret = -1;
2972

2973 2974
    virCheckFlags(0, -1);

2975
    testDriverLock(privconn);
2976

2977
    if (!(privdom = testDomObjFromDomain(domain)))
2978
        goto cleanup;
2979

J
Jiri Denemark 已提交
2980
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_SHUTOFF) {
2981 2982
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Domain '%s' is already running"), domain->name);
2983
        goto cleanup;
2984 2985
    }

2986
    if (testDomainStartState(privconn, privdom,
J
Jiri Denemark 已提交
2987
                             VIR_DOMAIN_RUNNING_BOOTED) < 0)
2988 2989 2990
        goto cleanup;
    domain->id = privdom->def->id;

2991
    event = virDomainEventLifecycleNewFromObj(privdom,
2992 2993
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
2994
    ret = 0;
2995

2996
 cleanup:
2997
    virDomainObjEndAPI(&privdom);
2998
    testObjectEventQueue(privconn, event);
2999
    testDriverUnlock(privconn);
3000
    return ret;
3001 3002
}

3003 3004
static int testDomainCreate(virDomainPtr domain)
{
3005 3006 3007
    return testDomainCreateWithFlags(domain, 0);
}

3008 3009 3010
static int testDomainUndefineFlags(virDomainPtr domain,
                                   unsigned int flags)
{
3011
    testDriverPtr privconn = domain->conn->privateData;
3012
    virDomainObjPtr privdom;
3013
    virObjectEventPtr event = NULL;
3014
    int nsnapshots;
3015
    int ret = -1;
3016

3017 3018
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
                  VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
3019

3020

3021
    if (!(privdom = testDomObjFromDomain(domain)))
3022
        goto cleanup;
3023

C
Cole Robinson 已提交
3024 3025 3026 3027 3028 3029 3030 3031
    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;
    }

3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049
    /* 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. */
    }

3050
    event = virDomainEventLifecycleNewFromObj(privdom,
3051 3052
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
C
Cole Robinson 已提交
3053 3054
    privdom->hasManagedSave = false;

3055
    if (virDomainObjIsActive(privdom))
3056
        privdom->persistent = 0;
3057
    else
3058
        virDomainObjListRemove(privconn->domains, privdom);
3059

3060
    ret = 0;
3061

3062
 cleanup:
3063
    virDomainObjEndAPI(&privdom);
3064
    testObjectEventQueue(privconn, event);
3065
    return ret;
3066 3067
}

3068 3069 3070 3071 3072
static int testDomainUndefine(virDomainPtr domain)
{
    return testDomainUndefineFlags(domain, 0);
}

3073 3074 3075
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
3076 3077
    virDomainObjPtr privdom;

3078 3079
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3080

3081
    *autostart = privdom->autostart;
3082

3083
    virDomainObjEndAPI(&privdom);
3084
    return 0;
3085 3086 3087 3088 3089 3090
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
3091 3092
    virDomainObjPtr privdom;

3093 3094
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3095

3096
    privdom->autostart = autostart ? 1 : 0;
3097

3098
    virDomainObjEndAPI(&privdom);
3099
    return 0;
3100
}
3101

3102
static char *testDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED,
3103 3104
                                        int *nparams)
{
3105 3106
    char *type = NULL;

3107 3108 3109
    if (nparams)
        *nparams = 1;

3110
    ignore_value(VIR_STRDUP(type, "fair"));
3111

3112 3113 3114
    return type;
}

3115
static int
3116 3117 3118 3119
testDomainGetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int *nparams,
                                      unsigned int flags)
3120
{
3121
    virDomainObjPtr privdom;
3122
    int ret = -1;
3123

3124 3125
    virCheckFlags(0, -1);

3126 3127
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3128

3129 3130
    if (virTypedParameterAssign(params, VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, 50) < 0)
3131
        goto cleanup;
3132 3133
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
3134 3135

    *nparams = 1;
3136 3137
    ret = 0;

3138
 cleanup:
3139
    virDomainObjEndAPI(&privdom);
3140
    return ret;
3141
}
3142

3143
static int
3144 3145 3146
testDomainGetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int *nparams)
3147
{
3148
    return testDomainGetSchedulerParametersFlags(domain, params, nparams, 0);
3149
}
3150

3151
static int
3152 3153 3154 3155
testDomainSetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int nparams,
                                      unsigned int flags)
3156
{
3157
    virDomainObjPtr privdom;
3158 3159
    int ret = -1;
    size_t i;
3160

3161
    virCheckFlags(0, -1);
3162 3163 3164 3165
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
3166
        return -1;
3167

3168 3169
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3170

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

3178 3179
    ret = 0;

3180
    virDomainObjEndAPI(&privdom);
3181
    return ret;
3182 3183
}

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

3192 3193
static int testDomainBlockStats(virDomainPtr domain,
                                const char *path,
3194
                                virDomainBlockStatsPtr stats)
3195 3196 3197 3198
{
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
3199
    int ret = -1;
3200

3201 3202 3203 3204 3205 3206
    if (!*path) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("summary statistics are not supported yet"));
        return ret;
    }

3207 3208
    if (!(privdom = testDomObjFromDomain(domain)))
        return ret;
3209

3210
    if (virDomainObjCheckActive(privdom) < 0)
3211 3212
        goto error;

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

    if (gettimeofday(&tv, NULL) < 0) {
3220
        virReportSystemError(errno,
3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233
                             "%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;
3234
 error:
3235
    virDomainObjEndAPI(&privdom);
3236 3237 3238
    return ret;
}

3239 3240 3241 3242
static int
testDomainInterfaceStats(virDomainPtr domain,
                         const char *device,
                         virDomainInterfaceStatsPtr stats)
3243 3244 3245 3246
{
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
M
Michal Privoznik 已提交
3247 3248 3249
    virDomainNetDefPtr net = NULL;
    int ret = -1;

3250

3251 3252
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3253

3254
    if (virDomainObjCheckActive(privdom) < 0)
3255 3256
        goto error;

3257
    if (!(net = virDomainNetFind(privdom->def, device)))
3258 3259 3260
        goto error;

    if (gettimeofday(&tv, NULL) < 0) {
3261
        virReportSystemError(errno,
3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277
                             "%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;
3278
 error:
3279
    virDomainObjEndAPI(&privdom);
3280 3281 3282
    return ret;
}

3283

3284 3285 3286 3287
static virNetworkObjPtr
testNetworkObjFindByUUID(testDriverPtr privconn,
                         const unsigned char *uuid)
{
3288
    virNetworkObjPtr obj;
3289 3290
    char uuidstr[VIR_UUID_STRING_BUFLEN];

3291
    if (!(obj = virNetworkObjFindByUUID(privconn->networks, uuid))) {
3292 3293 3294 3295 3296 3297
        virUUIDFormat(uuid, uuidstr);
        virReportError(VIR_ERR_NO_NETWORK,
                       _("no network with matching uuid '%s'"),
                       uuidstr);
    }

3298
    return obj;
3299 3300 3301
}


3302 3303 3304
static virNetworkPtr
testNetworkLookupByUUID(virConnectPtr conn,
                        const unsigned char *uuid)
3305
{
3306
    testDriverPtr privconn = conn->privateData;
3307
    virNetworkObjPtr obj;
3308
    virNetworkDefPtr def;
3309
    virNetworkPtr net = NULL;
3310

3311
    if (!(obj = testNetworkObjFindByUUID(privconn, uuid)))
3312
        goto cleanup;
3313
    def = virNetworkObjGetDef(obj);
3314

3315
    net = virGetNetwork(conn, def->name, def->uuid);
3316

3317
 cleanup:
3318 3319
    virNetworkObjEndAPI(&obj);
    return net;
3320
}
3321

3322 3323 3324 3325 3326

static virNetworkObjPtr
testNetworkObjFindByName(testDriverPtr privconn,
                         const char *name)
{
3327
    virNetworkObjPtr obj;
3328

3329
    if (!(obj = virNetworkObjFindByName(privconn->networks, name)))
3330 3331 3332 3333
        virReportError(VIR_ERR_NO_NETWORK,
                       _("no network with matching name '%s'"),
                       name);

3334
    return obj;
3335 3336 3337
}


3338 3339 3340
static virNetworkPtr
testNetworkLookupByName(virConnectPtr conn,
                        const char *name)
3341
{
3342
    testDriverPtr privconn = conn->privateData;
3343
    virNetworkObjPtr obj;
3344
    virNetworkDefPtr def;
3345
    virNetworkPtr net = NULL;
3346

3347
    if (!(obj = testNetworkObjFindByName(privconn, name)))
3348
        goto cleanup;
3349
    def = virNetworkObjGetDef(obj);
3350

3351
    net = virGetNetwork(conn, def->name, def->uuid);
3352

3353
 cleanup:
3354 3355
    virNetworkObjEndAPI(&obj);
    return net;
3356 3357 3358
}


3359 3360
static int
testConnectNumOfNetworks(virConnectPtr conn)
3361
{
3362
    testDriverPtr privconn = conn->privateData;
3363
    int numActive;
3364

3365 3366
    numActive = virNetworkObjListNumOfNetworks(privconn->networks,
                                               true, NULL, conn);
3367
    return numActive;
3368 3369
}

3370 3371 3372 3373

static int
testConnectListNetworks(virConnectPtr conn,
                        char **const names,
3374
                        int maxnames)
3375
{
3376
    testDriverPtr privconn = conn->privateData;
3377
    int n;
3378

3379
    n = virNetworkObjListGetNames(privconn->networks,
3380
                                  true, names, maxnames, NULL, conn);
3381
    return n;
3382 3383
}

3384 3385 3386

static int
testConnectNumOfDefinedNetworks(virConnectPtr conn)
3387
{
3388
    testDriverPtr privconn = conn->privateData;
3389
    int numInactive;
3390

3391 3392
    numInactive = virNetworkObjListNumOfNetworks(privconn->networks,
                                                 false, NULL, conn);
3393
    return numInactive;
3394 3395
}

3396 3397 3398 3399

static int
testConnectListDefinedNetworks(virConnectPtr conn,
                               char **const names,
3400
                               int maxnames)
3401
{
3402
    testDriverPtr privconn = conn->privateData;
3403
    int n;
3404

3405
    n = virNetworkObjListGetNames(privconn->networks,
3406
                                  false, names, maxnames, NULL, conn);
3407
    return n;
3408 3409
}

3410

3411
static int
3412
testConnectListAllNetworks(virConnectPtr conn,
3413 3414 3415
                           virNetworkPtr **nets,
                           unsigned int flags)
{
3416
    testDriverPtr privconn = conn->privateData;
3417 3418 3419

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

3420
    return virNetworkObjListExport(conn, privconn->networks, nets, NULL, flags);
3421
}
3422

3423 3424 3425

static int
testNetworkIsActive(virNetworkPtr net)
3426
{
3427
    testDriverPtr privconn = net->conn->privateData;
3428 3429 3430
    virNetworkObjPtr obj;
    int ret = -1;

3431
    if (!(obj = testNetworkObjFindByUUID(privconn, net->uuid)))
3432
        goto cleanup;
3433

3434 3435
    ret = virNetworkObjIsActive(obj);

3436
 cleanup:
3437
    virNetworkObjEndAPI(&obj);
3438 3439 3440
    return ret;
}

3441 3442 3443

static int
testNetworkIsPersistent(virNetworkPtr net)
3444
{
3445
    testDriverPtr privconn = net->conn->privateData;
3446 3447 3448
    virNetworkObjPtr obj;
    int ret = -1;

3449
    if (!(obj = testNetworkObjFindByUUID(privconn, net->uuid)))
3450
        goto cleanup;
3451

3452
    ret = virNetworkObjIsPersistent(obj);
3453

3454
 cleanup:
3455
    virNetworkObjEndAPI(&obj);
3456 3457 3458 3459
    return ret;
}


3460 3461
static virNetworkPtr
testNetworkCreateXML(virConnectPtr conn, const char *xml)
3462
{
3463
    testDriverPtr privconn = conn->privateData;
3464
    virNetworkDefPtr newDef;
3465
    virNetworkObjPtr obj = NULL;
3466
    virNetworkDefPtr def;
3467
    virNetworkPtr net = NULL;
3468
    virObjectEventPtr event = NULL;
3469

3470
    if ((newDef = virNetworkDefParseString(xml)) == NULL)
3471
        goto cleanup;
3472

3473
    if (!(obj = virNetworkObjAssignDef(privconn->networks, newDef,
3474 3475
                                       VIR_NETWORK_OBJ_LIST_ADD_LIVE |
                                       VIR_NETWORK_OBJ_LIST_ADD_CHECK_LIVE)))
3476
        goto cleanup;
3477 3478
    newDef = NULL;
    def = virNetworkObjGetDef(obj);
3479
    virNetworkObjSetActive(obj, true);
3480

3481
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
3482 3483
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3484

3485
    net = virGetNetwork(conn, def->name, def->uuid);
3486

3487
 cleanup:
3488
    virNetworkDefFree(newDef);
3489
    testObjectEventQueue(privconn, event);
3490 3491
    virNetworkObjEndAPI(&obj);
    return net;
3492 3493
}

3494 3495 3496 3497

static virNetworkPtr
testNetworkDefineXML(virConnectPtr conn,
                     const char *xml)
3498
{
3499
    testDriverPtr privconn = conn->privateData;
3500
    virNetworkDefPtr newDef;
3501
    virNetworkObjPtr obj = NULL;
3502
    virNetworkDefPtr def;
3503
    virNetworkPtr net = NULL;
3504
    virObjectEventPtr event = NULL;
3505

3506
    if ((newDef = virNetworkDefParseString(xml)) == NULL)
3507
        goto cleanup;
3508

3509
    if (!(obj = virNetworkObjAssignDef(privconn->networks, newDef, 0)))
3510
        goto cleanup;
3511 3512
    newDef = NULL;
    def = virNetworkObjGetDef(obj);
3513

3514
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
3515 3516
                                        VIR_NETWORK_EVENT_DEFINED,
                                        0);
3517

3518
    net = virGetNetwork(conn, def->name, def->uuid);
3519

3520
 cleanup:
3521
    virNetworkDefFree(newDef);
3522
    testObjectEventQueue(privconn, event);
3523 3524
    virNetworkObjEndAPI(&obj);
    return net;
3525 3526
}

3527 3528

static int
3529
testNetworkUndefine(virNetworkPtr net)
3530
{
3531 3532
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3533
    int ret = -1;
3534
    virObjectEventPtr event = NULL;
3535

3536
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3537
        goto cleanup;
3538

3539
    if (virNetworkObjIsActive(obj)) {
3540
        virReportError(VIR_ERR_OPERATION_INVALID,
3541
                       _("Network '%s' is still running"), net->name);
3542
        goto cleanup;
3543 3544
    }

3545
    event = virNetworkEventLifecycleNew(net->name, net->uuid,
3546 3547
                                        VIR_NETWORK_EVENT_UNDEFINED,
                                        0);
3548

3549
    virNetworkObjRemoveInactive(privconn->networks, obj);
3550
    ret = 0;
3551

3552
 cleanup:
3553
    testObjectEventQueue(privconn, event);
3554
    virNetworkObjEndAPI(&obj);
3555
    return ret;
3556 3557
}

3558

3559 3560 3561 3562 3563 3564 3565 3566
static int
testNetworkUpdate(virNetworkPtr net,
                  unsigned int command,
                  unsigned int section,
                  int parentIndex,
                  const char *xml,
                  unsigned int flags)
{
3567
    testDriverPtr privconn = net->conn->privateData;
3568
    virNetworkObjPtr obj = NULL;
3569 3570 3571 3572 3573 3574
    int isActive, ret = -1;

    virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
                  VIR_NETWORK_UPDATE_AFFECT_CONFIG,
                  -1);

3575
    if (!(obj = testNetworkObjFindByUUID(privconn, net->uuid)))
3576 3577 3578 3579 3580
        goto cleanup;

    /* VIR_NETWORK_UPDATE_AFFECT_CURRENT means "change LIVE if network
     * is active, else change CONFIG
    */
3581
    isActive = virNetworkObjIsActive(obj);
3582 3583 3584 3585 3586 3587 3588 3589 3590 3591
    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 */
3592
    if (virNetworkObjUpdate(obj, command, section, parentIndex, xml, flags) < 0)
3593 3594 3595
       goto cleanup;

    ret = 0;
3596
 cleanup:
3597
    virNetworkObjEndAPI(&obj);
3598 3599 3600
    return ret;
}

3601 3602

static int
3603
testNetworkCreate(virNetworkPtr net)
3604
{
3605 3606
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3607
    virNetworkDefPtr def;
3608
    int ret = -1;
3609
    virObjectEventPtr event = NULL;
3610

3611
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3612
        goto cleanup;
3613
    def = virNetworkObjGetDef(obj);
3614

3615
    if (virNetworkObjIsActive(obj)) {
3616
        virReportError(VIR_ERR_OPERATION_INVALID,
3617
                       _("Network '%s' is already running"), net->name);
3618
        goto cleanup;
3619 3620
    }

3621
    virNetworkObjSetActive(obj, true);
3622
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
3623 3624
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3625
    ret = 0;
3626

3627
 cleanup:
3628
    testObjectEventQueue(privconn, event);
3629
    virNetworkObjEndAPI(&obj);
3630
    return ret;
3631 3632
}

3633 3634

static int
3635
testNetworkDestroy(virNetworkPtr net)
3636
{
3637 3638
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3639
    virNetworkDefPtr def;
3640
    int ret = -1;
3641
    virObjectEventPtr event = NULL;
3642

3643
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3644
        goto cleanup;
3645
    def = virNetworkObjGetDef(obj);
3646

3647
    virNetworkObjSetActive(obj, false);
3648
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
3649 3650
                                        VIR_NETWORK_EVENT_STOPPED,
                                        0);
3651
    if (!virNetworkObjIsPersistent(obj))
3652
        virNetworkObjRemoveInactive(privconn->networks, obj);
3653

3654 3655
    ret = 0;

3656
 cleanup:
3657
    testObjectEventQueue(privconn, event);
3658
    virNetworkObjEndAPI(&obj);
3659
    return ret;
3660 3661
}

3662 3663

static char *
3664
testNetworkGetXMLDesc(virNetworkPtr net,
3665
                      unsigned int flags)
3666
{
3667 3668
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3669
    char *ret = NULL;
3670

E
Eric Blake 已提交
3671 3672
    virCheckFlags(0, NULL);

3673
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3674
        goto cleanup;
3675

3676
    ret = virNetworkDefFormat(virNetworkObjGetDef(obj), flags);
3677

3678
 cleanup:
3679
    virNetworkObjEndAPI(&obj);
3680
    return ret;
3681 3682
}

3683 3684

static char *
3685
testNetworkGetBridgeName(virNetworkPtr net)
3686
{
3687
    testDriverPtr privconn = net->conn->privateData;
3688
    char *bridge = NULL;
3689
    virNetworkObjPtr obj;
3690
    virNetworkDefPtr def;
3691

3692
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3693
        goto cleanup;
3694
    def = virNetworkObjGetDef(obj);
3695

3696
    if (!(def->bridge)) {
3697 3698
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("network '%s' does not have a bridge name."),
3699
                       def->name);
3700 3701 3702
        goto cleanup;
    }

3703
    ignore_value(VIR_STRDUP(bridge, def->bridge));
3704

3705
 cleanup:
3706
    virNetworkObjEndAPI(&obj);
3707 3708 3709
    return bridge;
}

3710 3711

static int
3712
testNetworkGetAutostart(virNetworkPtr net,
3713
                        int *autostart)
3714
{
3715 3716
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3717
    int ret = -1;
3718

3719
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3720
        goto cleanup;
3721

3722
    *autostart = virNetworkObjIsAutostart(obj) ? 1 : 0;
3723 3724
    ret = 0;

3725
 cleanup:
3726
    virNetworkObjEndAPI(&obj);
3727
    return ret;
3728 3729
}

3730 3731

static int
3732
testNetworkSetAutostart(virNetworkPtr net,
3733
                        int autostart)
3734
{
3735 3736
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3737
    bool new_autostart = (autostart != 0);
3738
    int ret = -1;
3739

3740
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3741
        goto cleanup;
3742

3743 3744
    virNetworkObjSetAutostart(obj, new_autostart);

3745 3746
    ret = 0;

3747
 cleanup:
3748
    virNetworkObjEndAPI(&obj);
3749
    return ret;
3750
}
3751

C
Cole Robinson 已提交
3752

L
Laine Stump 已提交
3753 3754 3755 3756 3757
/*
 * Physical host interface routines
 */


3758 3759 3760 3761
static virInterfaceObjPtr
testInterfaceObjFindByName(testDriverPtr privconn,
                           const char *name)
{
3762
    virInterfaceObjPtr obj;
3763 3764

    testDriverLock(privconn);
3765
    obj = virInterfaceObjListFindByName(privconn->ifaces, name);
3766 3767
    testDriverUnlock(privconn);

3768
    if (!obj)
3769 3770 3771 3772
        virReportError(VIR_ERR_NO_INTERFACE,
                       _("no interface with matching name '%s'"),
                       name);

3773
    return obj;
3774 3775 3776
}


3777 3778
static int
testConnectNumOfInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3779
{
3780
    testDriverPtr privconn = conn->privateData;
3781
    int ninterfaces;
L
Laine Stump 已提交
3782 3783

    testDriverLock(privconn);
3784
    ninterfaces = virInterfaceObjListNumOfInterfaces(privconn->ifaces, true);
L
Laine Stump 已提交
3785
    testDriverUnlock(privconn);
3786
    return ninterfaces;
L
Laine Stump 已提交
3787 3788
}

3789 3790 3791 3792 3793

static int
testConnectListInterfaces(virConnectPtr conn,
                          char **const names,
                          int maxnames)
L
Laine Stump 已提交
3794
{
3795
    testDriverPtr privconn = conn->privateData;
3796
    int nnames;
L
Laine Stump 已提交
3797 3798

    testDriverLock(privconn);
3799 3800
    nnames = virInterfaceObjListGetNames(privconn->ifaces, true,
                                         names, maxnames);
L
Laine Stump 已提交
3801 3802
    testDriverUnlock(privconn);

3803
    return nnames;
L
Laine Stump 已提交
3804 3805
}

3806 3807 3808

static int
testConnectNumOfDefinedInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3809
{
3810
    testDriverPtr privconn = conn->privateData;
3811
    int ninterfaces;
L
Laine Stump 已提交
3812 3813

    testDriverLock(privconn);
3814
    ninterfaces = virInterfaceObjListNumOfInterfaces(privconn->ifaces, false);
L
Laine Stump 已提交
3815
    testDriverUnlock(privconn);
3816
    return ninterfaces;
L
Laine Stump 已提交
3817 3818
}

3819 3820 3821 3822 3823

static int
testConnectListDefinedInterfaces(virConnectPtr conn,
                                 char **const names,
                                 int maxnames)
L
Laine Stump 已提交
3824
{
3825
    testDriverPtr privconn = conn->privateData;
3826
    int nnames;
L
Laine Stump 已提交
3827 3828

    testDriverLock(privconn);
3829 3830
    nnames = virInterfaceObjListGetNames(privconn->ifaces, false,
                                         names, maxnames);
L
Laine Stump 已提交
3831 3832
    testDriverUnlock(privconn);

3833
    return nnames;
L
Laine Stump 已提交
3834 3835
}

3836 3837 3838 3839

static virInterfacePtr
testInterfaceLookupByName(virConnectPtr conn,
                          const char *name)
L
Laine Stump 已提交
3840
{
3841
    testDriverPtr privconn = conn->privateData;
3842
    virInterfaceObjPtr obj;
3843
    virInterfaceDefPtr def;
L
Laine Stump 已提交
3844 3845
    virInterfacePtr ret = NULL;

3846
    if (!(obj = testInterfaceObjFindByName(privconn, name)))
3847
        return NULL;
3848
    def = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
3849

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

3852
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
3853 3854 3855
    return ret;
}

3856 3857 3858 3859

static virInterfacePtr
testInterfaceLookupByMACString(virConnectPtr conn,
                               const char *mac)
L
Laine Stump 已提交
3860
{
3861
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3862
    int ifacect;
3863
    char *ifacenames[] = { NULL, NULL };
L
Laine Stump 已提交
3864 3865 3866
    virInterfacePtr ret = NULL;

    testDriverLock(privconn);
3867 3868
    ifacect = virInterfaceObjListFindByMACString(privconn->ifaces, mac,
                                                 ifacenames, 2);
L
Laine Stump 已提交
3869 3870 3871
    testDriverUnlock(privconn);

    if (ifacect == 0) {
3872 3873
        virReportError(VIR_ERR_NO_INTERFACE,
                       _("no interface with matching mac '%s'"), mac);
L
Laine Stump 已提交
3874 3875 3876 3877
        goto cleanup;
    }

    if (ifacect > 1) {
3878
        virReportError(VIR_ERR_MULTIPLE_INTERFACES, NULL);
L
Laine Stump 已提交
3879 3880 3881
        goto cleanup;
    }

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

3884
 cleanup:
3885 3886
    VIR_FREE(ifacenames[0]);
    VIR_FREE(ifacenames[1]);
L
Laine Stump 已提交
3887 3888 3889
    return ret;
}

3890 3891 3892

static int
testInterfaceIsActive(virInterfacePtr iface)
3893
{
3894
    testDriverPtr privconn = iface->conn->privateData;
3895 3896 3897
    virInterfaceObjPtr obj;
    int ret = -1;

3898
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
3899
        return -1;
3900

3901 3902
    ret = virInterfaceObjIsActive(obj);

3903
    virInterfaceObjEndAPI(&obj);
3904 3905 3906
    return ret;
}

3907 3908 3909 3910

static int
testInterfaceChangeBegin(virConnectPtr conn,
                         unsigned int flags)
3911
{
3912
    testDriverPtr privconn = conn->privateData;
3913 3914
    int ret = -1;

E
Eric Blake 已提交
3915 3916
    virCheckFlags(0, -1);

3917 3918
    testDriverLock(privconn);
    if (privconn->transaction_running) {
3919
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3920
                       _("there is another transaction running."));
3921 3922 3923 3924 3925
        goto cleanup;
    }

    privconn->transaction_running = true;

3926
    if (!(privconn->backupIfaces = virInterfaceObjListClone(privconn->ifaces)))
3927 3928 3929
        goto cleanup;

    ret = 0;
3930
 cleanup:
3931 3932 3933 3934
    testDriverUnlock(privconn);
    return ret;
}

3935 3936 3937 3938

static int
testInterfaceChangeCommit(virConnectPtr conn,
                          unsigned int flags)
3939
{
3940
    testDriverPtr privconn = conn->privateData;
3941 3942
    int ret = -1;

E
Eric Blake 已提交
3943 3944
    virCheckFlags(0, -1);

3945 3946 3947
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3948
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3949 3950
                       _("no transaction running, "
                         "nothing to be committed."));
3951 3952 3953
        goto cleanup;
    }

3954
    virObjectUnref(privconn->backupIfaces);
3955 3956 3957 3958
    privconn->transaction_running = false;

    ret = 0;

3959
 cleanup:
3960 3961 3962 3963 3964
    testDriverUnlock(privconn);

    return ret;
}

3965 3966 3967 3968

static int
testInterfaceChangeRollback(virConnectPtr conn,
                            unsigned int flags)
3969
{
3970
    testDriverPtr privconn = conn->privateData;
3971 3972
    int ret = -1;

E
Eric Blake 已提交
3973 3974
    virCheckFlags(0, -1);

3975 3976 3977
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3978
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3979 3980
                       _("no transaction running, "
                         "nothing to rollback."));
3981 3982 3983
        goto cleanup;
    }

3984
    virObjectUnref(privconn->ifaces);
3985 3986
    privconn->ifaces = privconn->backupIfaces;
    privconn->backupIfaces = NULL;
3987 3988 3989 3990 3991

    privconn->transaction_running = false;

    ret = 0;

3992
 cleanup:
3993 3994 3995
    testDriverUnlock(privconn);
    return ret;
}
3996

3997 3998 3999 4000

static char *
testInterfaceGetXMLDesc(virInterfacePtr iface,
                        unsigned int flags)
L
Laine Stump 已提交
4001
{
4002
    testDriverPtr privconn = iface->conn->privateData;
4003
    virInterfaceObjPtr obj;
4004
    virInterfaceDefPtr def;
L
Laine Stump 已提交
4005 4006
    char *ret = NULL;

E
Eric Blake 已提交
4007 4008
    virCheckFlags(0, NULL);

4009
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
4010
        return NULL;
4011
    def = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
4012

4013
    ret = virInterfaceDefFormat(def);
L
Laine Stump 已提交
4014

4015
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
4016 4017 4018 4019
    return ret;
}


4020 4021 4022 4023
static virInterfacePtr
testInterfaceDefineXML(virConnectPtr conn,
                       const char *xmlStr,
                       unsigned int flags)
L
Laine Stump 已提交
4024
{
4025
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
4026
    virInterfaceDefPtr def;
4027
    virInterfaceObjPtr obj = NULL;
4028
    virInterfaceDefPtr objdef;
L
Laine Stump 已提交
4029 4030
    virInterfacePtr ret = NULL;

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

L
Laine Stump 已提交
4033
    testDriverLock(privconn);
4034
    if ((def = virInterfaceDefParseString(xmlStr)) == NULL)
L
Laine Stump 已提交
4035 4036
        goto cleanup;

4037
    if ((obj = virInterfaceObjListAssignDef(privconn->ifaces, def)) == NULL)
L
Laine Stump 已提交
4038 4039
        goto cleanup;
    def = NULL;
4040
    objdef = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
4041

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

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

4051 4052 4053

static int
testInterfaceUndefine(virInterfacePtr iface)
L
Laine Stump 已提交
4054
{
4055
    testDriverPtr privconn = iface->conn->privateData;
4056
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
4057

4058
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
4059
        return -1;
L
Laine Stump 已提交
4060

4061
    virInterfaceObjListRemove(privconn->ifaces, obj);
4062
    virObjectUnref(obj);
L
Laine Stump 已提交
4063

4064
    return 0;
L
Laine Stump 已提交
4065 4066
}

4067 4068 4069 4070

static int
testInterfaceCreate(virInterfacePtr iface,
                    unsigned int flags)
L
Laine Stump 已提交
4071
{
4072
    testDriverPtr privconn = iface->conn->privateData;
4073
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
4074 4075
    int ret = -1;

E
Eric Blake 已提交
4076 4077
    virCheckFlags(0, -1);

4078
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
4079
        return -1;
L
Laine Stump 已提交
4080

4081
    if (virInterfaceObjIsActive(obj)) {
4082
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
4083 4084 4085
        goto cleanup;
    }

4086
    virInterfaceObjSetActive(obj, true);
L
Laine Stump 已提交
4087 4088
    ret = 0;

4089
 cleanup:
4090
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
4091 4092 4093
    return ret;
}

4094 4095 4096 4097

static int
testInterfaceDestroy(virInterfacePtr iface,
                     unsigned int flags)
L
Laine Stump 已提交
4098
{
4099
    testDriverPtr privconn = iface->conn->privateData;
4100
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
4101 4102
    int ret = -1;

E
Eric Blake 已提交
4103 4104
    virCheckFlags(0, -1);

4105
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
4106
        return -1;
L
Laine Stump 已提交
4107

4108
    if (!virInterfaceObjIsActive(obj)) {
4109
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
4110 4111 4112
        goto cleanup;
    }

4113
    virInterfaceObjSetActive(obj, false);
L
Laine Stump 已提交
4114 4115
    ret = 0;

4116
 cleanup:
4117
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
4118 4119 4120 4121 4122
    return ret;
}



C
Cole Robinson 已提交
4123 4124 4125 4126
/*
 * Storage Driver routines
 */

4127
static int
4128
testStoragePoolObjSetDefaults(virStoragePoolObjPtr obj)
4129
{
4130
    char *configFile;
4131
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4132

4133 4134 4135
    def->capacity = defaultPoolCap;
    def->allocation = defaultPoolAlloc;
    def->available = defaultPoolCap - defaultPoolAlloc;
C
Cole Robinson 已提交
4136

4137 4138 4139 4140 4141
    if (VIR_STRDUP(configFile, "") < 0)
        return -1;

    virStoragePoolObjSetConfigFile(obj, configFile);
    return 0;
C
Cole Robinson 已提交
4142 4143
}

4144

4145 4146 4147 4148
static virStoragePoolObjPtr
testStoragePoolObjFindByName(testDriverPtr privconn,
                             const char *name)
{
4149
    virStoragePoolObjPtr obj;
4150 4151

    testDriverLock(privconn);
4152
    obj = virStoragePoolObjFindByName(privconn->pools, name);
4153 4154
    testDriverUnlock(privconn);

4155
    if (!obj)
4156 4157 4158 4159
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       name);

4160
    return obj;
4161 4162 4163
}


4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175
static virStoragePoolObjPtr
testStoragePoolObjFindActiveByName(testDriverPtr privconn,
                                   const char *name)
{
    virStoragePoolObjPtr obj;

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

    if (!virStoragePoolObjIsActive(obj)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), name);
4176
        virStoragePoolObjEndAPI(&obj);
4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195
        return NULL;
    }

    return obj;
}


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

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

    if (virStoragePoolObjIsActive(obj)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is active"), name);
4196
        virStoragePoolObjEndAPI(&obj);
4197 4198 4199 4200 4201 4202 4203
        return NULL;
    }

    return obj;
}


4204 4205 4206 4207
static virStoragePoolObjPtr
testStoragePoolObjFindByUUID(testDriverPtr privconn,
                             const unsigned char *uuid)
{
4208
    virStoragePoolObjPtr obj;
4209 4210 4211
    char uuidstr[VIR_UUID_STRING_BUFLEN];

    testDriverLock(privconn);
4212
    obj = virStoragePoolObjFindByUUID(privconn->pools, uuid);
4213 4214
    testDriverUnlock(privconn);

4215
    if (!obj) {
4216 4217 4218 4219 4220 4221
        virUUIDFormat(uuid, uuidstr);
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching uuid '%s'"),
                       uuidstr);
    }

4222
    return obj;
4223 4224 4225
}


C
Cole Robinson 已提交
4226 4227
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
4228 4229
                            const unsigned char *uuid)
{
4230
    testDriverPtr privconn = conn->privateData;
4231
    virStoragePoolObjPtr obj;
4232
    virStoragePoolDefPtr def;
4233
    virStoragePoolPtr pool = NULL;
C
Cole Robinson 已提交
4234

4235
    if (!(obj = testStoragePoolObjFindByUUID(privconn, uuid)))
4236
        return NULL;
4237
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4238

4239
    pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
4240

4241
    virStoragePoolObjEndAPI(&obj);
4242
    return pool;
C
Cole Robinson 已提交
4243 4244
}

4245

C
Cole Robinson 已提交
4246 4247
static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
4248 4249
                            const char *name)
{
4250
    testDriverPtr privconn = conn->privateData;
4251
    virStoragePoolObjPtr obj;
4252
    virStoragePoolDefPtr def;
4253
    virStoragePoolPtr pool = NULL;
C
Cole Robinson 已提交
4254

4255
    if (!(obj = testStoragePoolObjFindByName(privconn, name)))
4256
        return NULL;
4257
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4258

4259
    pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
4260

4261
    virStoragePoolObjEndAPI(&obj);
4262
    return pool;
C
Cole Robinson 已提交
4263 4264
}

4265

C
Cole Robinson 已提交
4266
static virStoragePoolPtr
4267 4268
testStoragePoolLookupByVolume(virStorageVolPtr vol)
{
C
Cole Robinson 已提交
4269 4270 4271
    return testStoragePoolLookupByName(vol->conn, vol->pool);
}

4272

C
Cole Robinson 已提交
4273
static int
4274 4275
testConnectNumOfStoragePools(virConnectPtr conn)
{
4276
    testDriverPtr privconn = conn->privateData;
4277
    int numActive = 0;
C
Cole Robinson 已提交
4278

4279
    testDriverLock(privconn);
4280
    numActive = virStoragePoolObjNumOfStoragePools(privconn->pools, conn,
4281
                                                   true, NULL);
4282
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4283 4284 4285 4286

    return numActive;
}

4287

C
Cole Robinson 已提交
4288
static int
4289 4290
testConnectListStoragePools(virConnectPtr conn,
                            char **const names,
4291
                            int maxnames)
4292
{
4293
    testDriverPtr privconn = conn->privateData;
4294
    int n = 0;
C
Cole Robinson 已提交
4295

4296
    testDriverLock(privconn);
4297
    n = virStoragePoolObjGetNames(privconn->pools, conn, true, NULL,
4298
                                  names, maxnames);
4299
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4300 4301 4302 4303

    return n;
}

4304

C
Cole Robinson 已提交
4305
static int
4306 4307
testConnectNumOfDefinedStoragePools(virConnectPtr conn)
{
4308
    testDriverPtr privconn = conn->privateData;
4309
    int numInactive = 0;
C
Cole Robinson 已提交
4310

4311
    testDriverLock(privconn);
4312
    numInactive = virStoragePoolObjNumOfStoragePools(privconn->pools, conn,
4313
                                                     false, NULL);
4314
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4315 4316 4317 4318

    return numInactive;
}

4319

C
Cole Robinson 已提交
4320
static int
4321 4322
testConnectListDefinedStoragePools(virConnectPtr conn,
                                   char **const names,
4323
                                   int maxnames)
4324
{
4325
    testDriverPtr privconn = conn->privateData;
4326
    int n = 0;
C
Cole Robinson 已提交
4327

4328
    testDriverLock(privconn);
4329
    n = virStoragePoolObjGetNames(privconn->pools, conn, false, NULL,
4330
                                  names, maxnames);
4331
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4332 4333 4334 4335

    return n;
}

4336

4337
static int
4338 4339 4340
testConnectListAllStoragePools(virConnectPtr conn,
                               virStoragePoolPtr **pools,
                               unsigned int flags)
4341
{
4342
    testDriverPtr privconn = conn->privateData;
4343 4344 4345 4346 4347
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

    testDriverLock(privconn);
4348
    ret = virStoragePoolObjListExport(conn, privconn->pools, pools,
4349
                                      NULL, flags);
4350 4351 4352 4353
    testDriverUnlock(privconn);

    return ret;
}
C
Cole Robinson 已提交
4354

4355 4356 4357

static int
testStoragePoolIsActive(virStoragePoolPtr pool)
4358
{
4359
    testDriverPtr privconn = pool->conn->privateData;
4360 4361 4362
    virStoragePoolObjPtr obj;
    int ret = -1;

4363
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
4364
        goto cleanup;
4365

4366 4367
    ret = virStoragePoolObjIsActive(obj);

4368
 cleanup:
4369
    if (obj)
4370
        virStoragePoolObjEndAPI(&obj);
4371 4372 4373
    return ret;
}

4374 4375 4376

static int
testStoragePoolIsPersistent(virStoragePoolPtr pool)
4377
{
4378
    testDriverPtr privconn = pool->conn->privateData;
4379 4380 4381
    virStoragePoolObjPtr obj;
    int ret = -1;

4382
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
4383
        return -1;
4384

4385
    ret = virStoragePoolObjGetConfigFile(obj) ? 1 : 0;
4386

4387
    virStoragePoolObjEndAPI(&obj);
4388 4389 4390 4391
    return ret;
}


C
Cole Robinson 已提交
4392
static int
4393 4394
testStoragePoolCreate(virStoragePoolPtr pool,
                      unsigned int flags)
E
Eric Blake 已提交
4395
{
4396
    testDriverPtr privconn = pool->conn->privateData;
4397
    virStoragePoolObjPtr obj;
4398
    virObjectEventPtr event = NULL;
4399

E
Eric Blake 已提交
4400 4401
    virCheckFlags(0, -1);

4402 4403
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
4404

4405
    virStoragePoolObjSetActive(obj, true);
4406 4407 4408 4409

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

4411
    testObjectEventQueue(privconn, event);
4412
    virStoragePoolObjEndAPI(&obj);
4413
    return 0;
C
Cole Robinson 已提交
4414 4415
}

4416

C
Cole Robinson 已提交
4417
static char *
4418 4419 4420 4421
testConnectFindStoragePoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type,
                                  const char *srcSpec,
                                  unsigned int flags)
C
Cole Robinson 已提交
4422
{
4423 4424 4425 4426
    virStoragePoolSourcePtr source = NULL;
    int pool_type;
    char *ret = NULL;

E
Eric Blake 已提交
4427 4428
    virCheckFlags(0, NULL);

4429 4430
    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
4431 4432
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
4433 4434 4435 4436
        goto cleanup;
    }

    if (srcSpec) {
4437
        source = virStoragePoolDefParseSourceString(srcSpec, pool_type);
4438 4439 4440 4441 4442 4443 4444
        if (!source)
            goto cleanup;
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
4445
        ignore_value(VIR_STRDUP(ret, defaultPoolSourcesLogicalXML));
4446 4447 4448
        break;

    case VIR_STORAGE_POOL_NETFS:
4449
        if (!source || !source->hosts[0].name) {
4450 4451
            virReportError(VIR_ERR_INVALID_ARG,
                           "%s", _("hostname must be specified for netfs sources"));
4452 4453 4454
            goto cleanup;
        }

4455 4456
        ignore_value(virAsprintf(&ret, defaultPoolSourcesNetFSXML,
                                 source->hosts[0].name));
4457 4458 4459
        break;

    default:
4460 4461
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source discovery"), type);
4462 4463
    }

4464
 cleanup:
4465 4466
    virStoragePoolSourceFree(source);
    return ret;
C
Cole Robinson 已提交
4467 4468 4469
}


4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491
static virNodeDeviceObjPtr
testNodeDeviceMockCreateVport(testDriverPtr driver,
                              const char *wwnn,
                              const char *wwpn);
static int
testCreateVport(testDriverPtr driver,
                const char *wwnn,
                const char *wwpn)
{
    virNodeDeviceObjPtr obj = NULL;
    /* The storage_backend_scsi createVport() will use the input adapter
     * fields parent name, parent_wwnn/parent_wwpn, or parent_fabric_wwn
     * in order to determine whether the provided parent can be used to
     * create a vHBA or will find "an available vport capable" to create
     * a vHBA. In order to do this, it uses the virVHBA* API's which traverse
     * the sysfs looking at various fields (rather than going via nodedev).
     *
     * Since the test environ doesn't have the sysfs for the storage pool
     * test, at least for now use the node device test infrastructure to
     * create the vHBA. In the long run the result is the same. */
    if (!(obj = testNodeDeviceMockCreateVport(driver, wwnn, wwpn)))
        return -1;
4492
    virNodeDeviceObjEndAPI(&obj);
4493 4494 4495 4496 4497

    return 0;
}


C
Cole Robinson 已提交
4498
static virStoragePoolPtr
4499 4500 4501
testStoragePoolCreateXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4502
{
4503
    testDriverPtr privconn = conn->privateData;
4504
    virStoragePoolDefPtr newDef;
4505
    virStoragePoolObjPtr obj = NULL;
4506
    virStoragePoolDefPtr def;
4507
    virStoragePoolPtr pool = NULL;
4508
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
4509

E
Eric Blake 已提交
4510 4511
    virCheckFlags(0, NULL);

4512
    testDriverLock(privconn);
4513
    if (!(newDef = virStoragePoolDefParseString(xml)))
4514
        goto cleanup;
C
Cole Robinson 已提交
4515

4516
    if (virStoragePoolObjIsDuplicate(privconn->pools, newDef, true) < 0)
4517
        goto cleanup;
C
Cole Robinson 已提交
4518

4519
    if (!(obj = virStoragePoolObjAssignDef(privconn->pools, newDef)))
4520
        goto cleanup;
4521 4522
    newDef = NULL;
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4523

4524
    if (def->source.adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
4525 4526 4527 4528 4529
        /* In the real code, we'd call virVHBAManageVport followed by
         * find_new_device, but we cannot do that here since we're not
         * mocking udev. The mock routine will copy an existing vHBA and
         * rename a few fields to mock that. */
        if (testCreateVport(privconn,
4530 4531
                            def->source.adapter.data.fchost.wwnn,
                            def->source.adapter.data.fchost.wwpn) < 0) {
4532
            virStoragePoolObjRemove(privconn->pools, obj);
4533
            virObjectUnref(obj);
4534
            obj = NULL;
4535 4536 4537 4538
            goto cleanup;
        }
    }

4539
    if (testStoragePoolObjSetDefaults(obj) == -1) {
4540
        virStoragePoolObjRemove(privconn->pools, obj);
4541
        virObjectUnref(obj);
4542
        obj = NULL;
4543
        goto cleanup;
C
Cole Robinson 已提交
4544
    }
4545 4546 4547 4548

    /* *SetDefaults fills this in for the persistent pools, but this
     * would be a transient pool so remove it; otherwise, the Destroy
     * code will not Remove the pool */
4549
    virStoragePoolObjSetConfigFile(obj, NULL);
4550

4551
    virStoragePoolObjSetActive(obj, true);
C
Cole Robinson 已提交
4552

4553
    event = virStoragePoolEventLifecycleNew(def->name, def->uuid,
4554 4555 4556
                                            VIR_STORAGE_POOL_EVENT_STARTED,
                                            0);

4557
    pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
4558

4559
 cleanup:
4560
    virStoragePoolDefFree(newDef);
4561
    testObjectEventQueue(privconn, event);
4562
    virStoragePoolObjEndAPI(&obj);
4563
    testDriverUnlock(privconn);
4564
    return pool;
C
Cole Robinson 已提交
4565 4566
}

4567

C
Cole Robinson 已提交
4568
static virStoragePoolPtr
4569 4570 4571
testStoragePoolDefineXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4572
{
4573
    testDriverPtr privconn = conn->privateData;
4574
    virStoragePoolDefPtr newDef;
4575
    virStoragePoolObjPtr obj = NULL;
4576
    virStoragePoolDefPtr def;
4577
    virStoragePoolPtr pool = NULL;
4578
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
4579

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

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

4586 4587 4588
    newDef->capacity = defaultPoolCap;
    newDef->allocation = defaultPoolAlloc;
    newDef->available = defaultPoolCap - defaultPoolAlloc;
C
Cole Robinson 已提交
4589

4590 4591 4592
    if (virStoragePoolObjIsDuplicate(privconn->pools, newDef, false) < 0)
        goto cleanup;

4593
    if (!(obj = virStoragePoolObjAssignDef(privconn->pools, newDef)))
4594
        goto cleanup;
4595 4596
    newDef = NULL;
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4597

4598
    event = virStoragePoolEventLifecycleNew(def->name, def->uuid,
4599 4600 4601
                                            VIR_STORAGE_POOL_EVENT_DEFINED,
                                            0);

4602
    if (testStoragePoolObjSetDefaults(obj) == -1) {
4603
        virStoragePoolObjRemove(privconn->pools, obj);
4604
        virObjectUnref(obj);
4605
        obj = NULL;
4606
        goto cleanup;
C
Cole Robinson 已提交
4607 4608
    }

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

4611
 cleanup:
4612
    virStoragePoolDefFree(newDef);
4613
    testObjectEventQueue(privconn, event);
4614
    virStoragePoolObjEndAPI(&obj);
4615
    testDriverUnlock(privconn);
4616
    return pool;
C
Cole Robinson 已提交
4617 4618
}

4619

C
Cole Robinson 已提交
4620
static int
4621 4622
testStoragePoolUndefine(virStoragePoolPtr pool)
{
4623
    testDriverPtr privconn = pool->conn->privateData;
4624
    virStoragePoolObjPtr obj;
4625
    virObjectEventPtr event = NULL;
4626

4627 4628
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
4629

4630 4631 4632 4633
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_UNDEFINED,
                                            0);

4634
    virStoragePoolObjRemove(privconn->pools, obj);
4635
    virObjectUnref(obj);
C
Cole Robinson 已提交
4636

4637
    testObjectEventQueue(privconn, event);
4638
    return 0;
C
Cole Robinson 已提交
4639 4640
}

4641

C
Cole Robinson 已提交
4642
static int
4643
testStoragePoolBuild(virStoragePoolPtr pool,
E
Eric Blake 已提交
4644 4645
                     unsigned int flags)
{
4646
    testDriverPtr privconn = pool->conn->privateData;
4647
    virStoragePoolObjPtr obj;
4648
    virObjectEventPtr event = NULL;
4649

E
Eric Blake 已提交
4650 4651
    virCheckFlags(0, -1);

4652 4653
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
4654

4655 4656 4657 4658
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_CREATED,
                                            0);

4659
    virStoragePoolObjEndAPI(&obj);
4660 4661

    testObjectEventQueue(privconn, event);
4662
    return 0;
C
Cole Robinson 已提交
4663 4664 4665
}


4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680
static int
testDestroyVport(testDriverPtr privconn,
                 const char *wwnn ATTRIBUTE_UNUSED,
                 const char *wwpn ATTRIBUTE_UNUSED)
{
    virNodeDeviceObjPtr obj = NULL;
    virObjectEventPtr event = NULL;

    /* NB: Cannot use virVHBAGetHostByWWN (yet) like the storage_backend_scsi
     * deleteVport() helper since that traverses the file system looking for
     * the wwnn/wwpn. So our choice short term is to cheat and use the name
     * (scsi_host12) we know was created.
     *
     * Reaching across the boundaries of space and time into the
     * Node Device in order to remove */
4681 4682
    if (!(obj = virNodeDeviceObjListFindByName(privconn->devs,
                                               "scsi_host12"))) {
4683 4684
        virReportError(VIR_ERR_NO_NODE_DEVICE, "%s",
                       _("no node device with matching name 'scsi_host12'"));
4685
        return -1;
4686 4687 4688 4689 4690 4691
    }

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

4692
    virNodeDeviceObjListRemove(privconn->devs, obj);
4693
    virObjectUnref(obj);
4694 4695

    testObjectEventQueue(privconn, event);
4696
    return 0;
4697 4698 4699
}


C
Cole Robinson 已提交
4700
static int
4701 4702
testStoragePoolDestroy(virStoragePoolPtr pool)
{
4703
    testDriverPtr privconn = pool->conn->privateData;
4704
    virStoragePoolObjPtr obj;
4705
    virStoragePoolDefPtr def;
4706
    int ret = -1;
4707
    virObjectEventPtr event = NULL;
4708

4709
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
4710
        return -1;
4711
    def = virStoragePoolObjGetDef(obj);
4712

4713
    virStoragePoolObjSetActive(obj, false);
4714

4715
    if (def->source.adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
4716
        if (testDestroyVport(privconn,
4717 4718
                             def->source.adapter.data.fchost.wwnn,
                             def->source.adapter.data.fchost.wwpn) < 0)
4719 4720 4721
            goto cleanup;
    }

4722 4723
    event = virStoragePoolEventLifecycleNew(def->name,
                                            def->uuid,
4724 4725
                                            VIR_STORAGE_POOL_EVENT_STOPPED,
                                            0);
C
Cole Robinson 已提交
4726

4727
    if (!(virStoragePoolObjGetConfigFile(obj))) {
4728
        virStoragePoolObjRemove(privconn->pools, obj);
4729
        virObjectUnref(obj);
4730
        obj = NULL;
4731
    }
4732
    ret = 0;
C
Cole Robinson 已提交
4733

4734
 cleanup:
4735
    testObjectEventQueue(privconn, event);
4736
    virStoragePoolObjEndAPI(&obj);
4737
    return ret;
C
Cole Robinson 已提交
4738 4739 4740 4741
}


static int
4742
testStoragePoolDelete(virStoragePoolPtr pool,
E
Eric Blake 已提交
4743 4744
                      unsigned int flags)
{
4745
    testDriverPtr privconn = pool->conn->privateData;
4746
    virStoragePoolObjPtr obj;
4747
    virObjectEventPtr event = NULL;
4748

E
Eric Blake 已提交
4749 4750
    virCheckFlags(0, -1);

4751 4752
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
4753

4754 4755 4756 4757 4758 4759
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_DELETED,
                                            0);

    testObjectEventQueue(privconn, event);

4760
    virStoragePoolObjEndAPI(&obj);
4761
    return 0;
C
Cole Robinson 已提交
4762 4763 4764 4765
}


static int
4766
testStoragePoolRefresh(virStoragePoolPtr pool,
E
Eric Blake 已提交
4767 4768
                       unsigned int flags)
{
4769
    testDriverPtr privconn = pool->conn->privateData;
4770
    virStoragePoolObjPtr obj;
4771
    virObjectEventPtr event = NULL;
4772

E
Eric Blake 已提交
4773 4774
    virCheckFlags(0, -1);

4775 4776
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return -1;
4777

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

4780
    testObjectEventQueue(privconn, event);
4781
    virStoragePoolObjEndAPI(&obj);
4782
    return 0;
C
Cole Robinson 已提交
4783 4784 4785 4786
}


static int
4787
testStoragePoolGetInfo(virStoragePoolPtr pool,
4788 4789
                       virStoragePoolInfoPtr info)
{
4790
    testDriverPtr privconn = pool->conn->privateData;
4791
    virStoragePoolObjPtr obj;
4792
    virStoragePoolDefPtr def;
4793

4794
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
4795
        return -1;
4796
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4797 4798

    memset(info, 0, sizeof(virStoragePoolInfo));
4799
    if (virStoragePoolObjIsActive(obj))
C
Cole Robinson 已提交
4800 4801 4802
        info->state = VIR_STORAGE_POOL_RUNNING;
    else
        info->state = VIR_STORAGE_POOL_INACTIVE;
4803 4804 4805
    info->capacity = def->capacity;
    info->allocation = def->allocation;
    info->available = def->available;
C
Cole Robinson 已提交
4806

4807
    virStoragePoolObjEndAPI(&obj);
4808
    return 0;
C
Cole Robinson 已提交
4809 4810
}

4811

C
Cole Robinson 已提交
4812
static char *
4813
testStoragePoolGetXMLDesc(virStoragePoolPtr pool,
E
Eric Blake 已提交
4814 4815
                          unsigned int flags)
{
4816
    testDriverPtr privconn = pool->conn->privateData;
4817
    virStoragePoolObjPtr obj;
4818
    char *ret = NULL;
4819

E
Eric Blake 已提交
4820 4821
    virCheckFlags(0, NULL);

4822
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
4823
        return NULL;
4824

4825
    ret = virStoragePoolDefFormat(virStoragePoolObjGetDef(obj));
4826

4827
    virStoragePoolObjEndAPI(&obj);
4828
    return ret;
C
Cole Robinson 已提交
4829 4830
}

4831

C
Cole Robinson 已提交
4832
static int
4833
testStoragePoolGetAutostart(virStoragePoolPtr pool,
4834 4835
                            int *autostart)
{
4836
    testDriverPtr privconn = pool->conn->privateData;
4837
    virStoragePoolObjPtr obj;
4838

4839
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
4840
        return -1;
C
Cole Robinson 已提交
4841

4842
    if (!virStoragePoolObjGetConfigFile(obj))
C
Cole Robinson 已提交
4843
        *autostart = 0;
4844
    else
4845
        *autostart = virStoragePoolObjIsAutostart(obj) ? 1 : 0;
C
Cole Robinson 已提交
4846

4847
    virStoragePoolObjEndAPI(&obj);
4848
    return 0;
C
Cole Robinson 已提交
4849 4850
}

4851

C
Cole Robinson 已提交
4852
static int
4853
testStoragePoolSetAutostart(virStoragePoolPtr pool,
4854 4855
                            int autostart)
{
4856
    testDriverPtr privconn = pool->conn->privateData;
4857
    virStoragePoolObjPtr obj;
4858
    bool new_autostart = (autostart != 0);
4859
    int ret = -1;
4860

4861
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
4862
        return -1;
C
Cole Robinson 已提交
4863

4864
    if (!virStoragePoolObjGetConfigFile(obj)) {
4865 4866
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("pool has no config file"));
4867
        goto cleanup;
C
Cole Robinson 已提交
4868 4869
    }

4870
    virStoragePoolObjSetAutostart(obj, new_autostart);
4871 4872
    ret = 0;

4873
 cleanup:
4874
    virStoragePoolObjEndAPI(&obj);
4875
    return ret;
C
Cole Robinson 已提交
4876 4877 4878 4879
}


static int
4880 4881
testStoragePoolNumOfVolumes(virStoragePoolPtr pool)
{
4882
    testDriverPtr privconn = pool->conn->privateData;
4883
    virStoragePoolObjPtr obj;
4884
    int ret = -1;
4885

4886 4887
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
4888

4889
    ret = virStoragePoolObjNumOfVolumes(obj, pool->conn, NULL);
4890

4891
    virStoragePoolObjEndAPI(&obj);
4892
    return ret;
C
Cole Robinson 已提交
4893 4894
}

4895

C
Cole Robinson 已提交
4896
static int
4897
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4898
                           char **const names,
4899 4900
                           int maxnames)
{
4901
    testDriverPtr privconn = pool->conn->privateData;
4902
    virStoragePoolObjPtr obj;
4903
    int n = -1;
4904

4905
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
4906
        return -1;
4907

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

4910
    virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
4911 4912 4913
    return n;
}

4914

4915
static int
4916
testStoragePoolListAllVolumes(virStoragePoolPtr pool,
4917
                              virStorageVolPtr **vols,
4918 4919
                              unsigned int flags)
{
4920 4921
    testDriverPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr obj;
4922 4923 4924 4925
    int ret = -1;

    virCheckFlags(0, -1);

4926
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
4927
        return -1;
4928

4929
    if (!virStoragePoolObjIsActive(obj)) {
4930 4931 4932 4933 4934
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("storage pool is not active"));
        goto cleanup;
    }

4935
    ret = virStoragePoolObjVolumeListExport(pool->conn, obj, vols, NULL);
4936 4937

 cleanup:
4938
    virStoragePoolObjEndAPI(&obj);
4939 4940 4941

    return ret;
}
C
Cole Robinson 已提交
4942

4943

4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958
static virStorageVolDefPtr
testStorageVolDefFindByName(virStoragePoolObjPtr obj,
                            const char *name)
{
    virStorageVolDefPtr privvol;

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

    return privvol;
}


C
Cole Robinson 已提交
4959
static virStorageVolPtr
4960
testStorageVolLookupByName(virStoragePoolPtr pool,
4961
                           const char *name)
4962
{
4963
    testDriverPtr privconn = pool->conn->privateData;
4964
    virStoragePoolObjPtr obj;
4965
    virStoragePoolDefPtr def;
4966
    virStorageVolDefPtr privvol;
4967
    virStorageVolPtr ret = NULL;
4968

4969 4970
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return NULL;
4971
    def = virStoragePoolObjGetDef(obj);
4972

4973
    if (!(privvol = testStorageVolDefFindByName(obj, name)))
4974
        goto cleanup;
C
Cole Robinson 已提交
4975

4976
    ret = virGetStorageVol(pool->conn, def->name,
4977 4978
                           privvol->name, privvol->key,
                           NULL, NULL);
4979

4980
 cleanup:
4981
    virStoragePoolObjEndAPI(&obj);
4982
    return ret;
C
Cole Robinson 已提交
4983 4984 4985
}


4986 4987 4988 4989 4990 4991 4992 4993 4994 4995
struct storageVolLookupData {
    const char *key;
    const char *path;
    virStorageVolDefPtr voldef;
};

static bool
testStorageVolLookupByKeyCallback(virStoragePoolObjPtr obj,
                                  const void *opaque)
{
4996
    struct storageVolLookupData *data = (struct storageVolLookupData *)opaque;
4997 4998 4999 5000 5001 5002 5003 5004

    if (virStoragePoolObjIsActive(obj))
        data->voldef = virStorageVolDefFindByKey(obj, data->key);

    return !!data->voldef;
}


C
Cole Robinson 已提交
5005
static virStorageVolPtr
5006
testStorageVolLookupByKey(virConnectPtr conn,
5007 5008
                          const char *key)
{
5009
    testDriverPtr privconn = conn->privateData;
5010
    virStoragePoolObjPtr obj;
5011
    virStoragePoolDefPtr def;
5012
    struct storageVolLookupData data = {
5013
        .key = key, .voldef = NULL };
5014
    virStorageVolPtr vol = NULL;
C
Cole Robinson 已提交
5015

5016
    testDriverLock(privconn);
5017
    if ((obj = virStoragePoolObjListSearch(privconn->pools,
5018 5019
                                           testStorageVolLookupByKeyCallback,
                                           &data)) && data.voldef) {
5020
        def = virStoragePoolObjGetDef(obj);
5021 5022 5023
        vol = virGetStorageVol(conn, def->name,
                               data.voldef->name, data.voldef->key,
                               NULL, NULL);
5024
        virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
5025
    }
5026
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
5027

5028
    if (!vol)
5029 5030
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching key '%s'"), key);
5031

5032 5033 5034 5035 5036 5037 5038 5039
    return vol;
}


static bool
testStorageVolLookupByPathCallback(virStoragePoolObjPtr obj,
                                   const void *opaque)
{
5040
    struct storageVolLookupData *data = (struct storageVolLookupData *)opaque;
5041 5042 5043 5044 5045

    if (virStoragePoolObjIsActive(obj))
        data->voldef = virStorageVolDefFindByPath(obj, data->path);

    return !!data->voldef;
C
Cole Robinson 已提交
5046 5047
}

5048

C
Cole Robinson 已提交
5049
static virStorageVolPtr
5050
testStorageVolLookupByPath(virConnectPtr conn,
5051 5052
                           const char *path)
{
5053
    testDriverPtr privconn = conn->privateData;
5054
    virStoragePoolObjPtr obj;
5055
    virStoragePoolDefPtr def;
5056
    struct storageVolLookupData data = {
5057
        .path = path, .voldef = NULL };
5058
    virStorageVolPtr vol = NULL;
C
Cole Robinson 已提交
5059

5060
    testDriverLock(privconn);
5061
    if ((obj = virStoragePoolObjListSearch(privconn->pools,
5062 5063
                                           testStorageVolLookupByPathCallback,
                                           &data)) && data.voldef) {
5064
        def = virStoragePoolObjGetDef(obj);
5065 5066 5067
        vol = virGetStorageVol(conn, def->name,
                               data.voldef->name, data.voldef->key,
                               NULL, NULL);
5068
        virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
5069
    }
5070
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
5071

5072
    if (!vol)
5073 5074
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching path '%s'"), path);
5075

5076
    return vol;
C
Cole Robinson 已提交
5077 5078
}

5079

C
Cole Robinson 已提交
5080
static virStorageVolPtr
5081 5082 5083
testStorageVolCreateXML(virStoragePoolPtr pool,
                        const char *xmldesc,
                        unsigned int flags)
E
Eric Blake 已提交
5084
{
5085
    testDriverPtr privconn = pool->conn->privateData;
5086
    virStoragePoolObjPtr obj;
5087
    virStoragePoolDefPtr def;
5088 5089
    virStorageVolDefPtr privvol = NULL;
    virStorageVolPtr ret = NULL;
5090

E
Eric Blake 已提交
5091 5092
    virCheckFlags(0, NULL);

5093 5094
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return NULL;
5095
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
5096

5097
    privvol = virStorageVolDefParseString(def, xmldesc, 0);
5098
    if (privvol == NULL)
5099
        goto cleanup;
5100

5101
    if (virStorageVolDefFindByName(obj, privvol->name)) {
5102 5103
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
5104
        goto cleanup;
C
Cole Robinson 已提交
5105 5106 5107
    }

    /* Make sure enough space */
5108 5109
    if ((def->allocation + privvol->target.allocation) >
         def->capacity) {
5110 5111 5112
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
5113
        goto cleanup;
C
Cole Robinson 已提交
5114 5115
    }

5116
    if (virAsprintf(&privvol->target.path, "%s/%s",
5117
                    def->target.path, privvol->name) < 0)
5118
        goto cleanup;
C
Cole Robinson 已提交
5119

5120
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
5121
        virStoragePoolObjAddVol(obj, privvol) < 0)
5122
        goto cleanup;
C
Cole Robinson 已提交
5123

5124 5125
    def->allocation += privvol->target.allocation;
    def->available = (def->capacity - def->allocation);
C
Cole Robinson 已提交
5126

5127
    ret = virGetStorageVol(pool->conn, def->name,
5128 5129
                           privvol->name, privvol->key,
                           NULL, NULL);
5130
    privvol = NULL;
5131

5132
 cleanup:
5133
    virStorageVolDefFree(privvol);
5134
    virStoragePoolObjEndAPI(&obj);
5135
    return ret;
C
Cole Robinson 已提交
5136 5137
}

5138

5139
static virStorageVolPtr
5140 5141 5142 5143
testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
                            const char *xmldesc,
                            virStorageVolPtr clonevol,
                            unsigned int flags)
E
Eric Blake 已提交
5144
{
5145
    testDriverPtr privconn = pool->conn->privateData;
5146
    virStoragePoolObjPtr obj;
5147
    virStoragePoolDefPtr def;
5148 5149 5150
    virStorageVolDefPtr privvol = NULL, origvol = NULL;
    virStorageVolPtr ret = NULL;

E
Eric Blake 已提交
5151 5152
    virCheckFlags(0, NULL);

5153 5154
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return NULL;
5155
    def = virStoragePoolObjGetDef(obj);
5156

5157
    privvol = virStorageVolDefParseString(def, xmldesc, 0);
5158 5159 5160
    if (privvol == NULL)
        goto cleanup;

5161
    if (virStorageVolDefFindByName(obj, privvol->name)) {
5162 5163
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
5164 5165 5166
        goto cleanup;
    }

5167
    origvol = virStorageVolDefFindByName(obj, clonevol->name);
5168
    if (!origvol) {
5169 5170 5171
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       clonevol->name);
5172 5173 5174 5175
        goto cleanup;
    }

    /* Make sure enough space */
5176
    if ((def->allocation + privvol->target.allocation) > def->capacity) {
5177 5178 5179
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
5180 5181
        goto cleanup;
    }
5182
    def->available = (def->capacity - def->allocation);
5183

5184
    if (virAsprintf(&privvol->target.path, "%s/%s",
5185
                    def->target.path, privvol->name) < 0)
5186 5187
        goto cleanup;

5188
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
5189
        virStoragePoolObjAddVol(obj, privvol) < 0)
5190 5191
        goto cleanup;

5192 5193
    def->allocation += privvol->target.allocation;
    def->available = (def->capacity - def->allocation);
5194

5195
    ret = virGetStorageVol(pool->conn, def->name,
5196 5197
                           privvol->name, privvol->key,
                           NULL, NULL);
5198 5199
    privvol = NULL;

5200
 cleanup:
5201
    virStorageVolDefFree(privvol);
5202
    virStoragePoolObjEndAPI(&obj);
5203 5204 5205
    return ret;
}

5206

C
Cole Robinson 已提交
5207
static int
5208 5209
testStorageVolDelete(virStorageVolPtr vol,
                     unsigned int flags)
E
Eric Blake 已提交
5210
{
5211
    testDriverPtr privconn = vol->conn->privateData;
5212
    virStoragePoolObjPtr obj;
5213
    virStoragePoolDefPtr def;
5214
    virStorageVolDefPtr privvol;
5215
    int ret = -1;
C
Cole Robinson 已提交
5216

E
Eric Blake 已提交
5217 5218
    virCheckFlags(0, -1);

5219 5220
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return -1;
5221
    def = virStoragePoolObjGetDef(obj);
5222

5223
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
5224
        goto cleanup;
5225

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

5229
    virStoragePoolObjRemoveVol(obj, privvol);
C
Cole Robinson 已提交
5230

5231
    ret = 0;
C
Cole Robinson 已提交
5232

5233
 cleanup:
5234
    virStoragePoolObjEndAPI(&obj);
5235
    return ret;
C
Cole Robinson 已提交
5236 5237 5238
}


5239 5240
static int
testStorageVolumeTypeForPool(int pooltype)
5241
{
C
Cole Robinson 已提交
5242

5243
    switch (pooltype) {
C
Cole Robinson 已提交
5244 5245 5246 5247 5248 5249 5250 5251 5252
        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;
    }
}

5253

C
Cole Robinson 已提交
5254
static int
5255
testStorageVolGetInfo(virStorageVolPtr vol,
5256 5257
                      virStorageVolInfoPtr info)
{
5258
    testDriverPtr privconn = vol->conn->privateData;
5259
    virStoragePoolObjPtr obj;
5260
    virStoragePoolDefPtr def;
5261
    virStorageVolDefPtr privvol;
5262
    int ret = -1;
5263

5264 5265
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return -1;
5266
    def = virStoragePoolObjGetDef(obj);
5267

5268
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
5269
        goto cleanup;
5270

C
Cole Robinson 已提交
5271
    memset(info, 0, sizeof(*info));
5272
    info->type = testStorageVolumeTypeForPool(def->type);
5273 5274
    info->capacity = privvol->target.capacity;
    info->allocation = privvol->target.allocation;
5275
    ret = 0;
C
Cole Robinson 已提交
5276

5277
 cleanup:
5278
    virStoragePoolObjEndAPI(&obj);
5279
    return ret;
C
Cole Robinson 已提交
5280 5281
}

5282

C
Cole Robinson 已提交
5283
static char *
5284 5285
testStorageVolGetXMLDesc(virStorageVolPtr vol,
                         unsigned int flags)
E
Eric Blake 已提交
5286
{
5287
    testDriverPtr privconn = vol->conn->privateData;
5288
    virStoragePoolObjPtr obj;
5289
    virStorageVolDefPtr privvol;
5290
    char *ret = NULL;
5291

E
Eric Blake 已提交
5292 5293
    virCheckFlags(0, NULL);

5294 5295
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return NULL;
5296

5297
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
5298
        goto cleanup;
C
Cole Robinson 已提交
5299

5300
    ret = virStorageVolDefFormat(virStoragePoolObjGetDef(obj), privvol);
5301

5302
 cleanup:
5303
    virStoragePoolObjEndAPI(&obj);
5304
    return ret;
C
Cole Robinson 已提交
5305 5306
}

5307

C
Cole Robinson 已提交
5308
static char *
5309 5310
testStorageVolGetPath(virStorageVolPtr vol)
{
5311
    testDriverPtr privconn = vol->conn->privateData;
5312
    virStoragePoolObjPtr obj;
5313
    virStorageVolDefPtr privvol;
5314
    char *ret = NULL;
5315

5316 5317
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return NULL;
5318

5319
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
5320
        goto cleanup;
5321

5322
    ignore_value(VIR_STRDUP(ret, privvol->target.path));
5323

5324
 cleanup:
5325
    virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
5326 5327 5328
    return ret;
}

5329

5330
/* Node device implementations */
5331

5332 5333 5334 5335 5336 5337
static virNodeDeviceObjPtr
testNodeDeviceObjFindByName(testDriverPtr driver,
                            const char *name)
{
    virNodeDeviceObjPtr obj;

5338
    if (!(obj = virNodeDeviceObjListFindByName(driver->devs, name)))
5339 5340 5341 5342 5343 5344 5345 5346
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       name);

    return obj;
}


5347 5348 5349
static int
testNodeNumOfDevices(virConnectPtr conn,
                     const char *cap,
E
Eric Blake 已提交
5350
                     unsigned int flags)
5351
{
5352
    testDriverPtr driver = conn->privateData;
5353

E
Eric Blake 已提交
5354 5355
    virCheckFlags(0, -1);

5356
    return virNodeDeviceObjListNumOfDevices(driver->devs, conn, cap, NULL);
5357 5358
}

5359

5360 5361 5362 5363 5364
static int
testNodeListDevices(virConnectPtr conn,
                    const char *cap,
                    char **const names,
                    int maxnames,
E
Eric Blake 已提交
5365
                    unsigned int flags)
5366
{
5367
    testDriverPtr driver = conn->privateData;
5368

E
Eric Blake 已提交
5369 5370
    virCheckFlags(0, -1);

5371 5372
    return virNodeDeviceObjListGetNames(driver->devs, conn, NULL,
                                        cap, names, maxnames);
5373 5374
}

5375

5376 5377 5378
static virNodeDevicePtr
testNodeDeviceLookupByName(virConnectPtr conn, const char *name)
{
5379
    testDriverPtr driver = conn->privateData;
5380
    virNodeDeviceObjPtr obj;
5381
    virNodeDeviceDefPtr def;
5382 5383
    virNodeDevicePtr ret = NULL;

5384
    if (!(obj = testNodeDeviceObjFindByName(driver, name)))
5385
        return NULL;
5386
    def = virNodeDeviceObjGetDef(obj);
5387

5388
    if ((ret = virGetNodeDevice(conn, name))) {
5389
        if (VIR_STRDUP(ret->parentName, def->parent) < 0) {
5390
            virObjectUnref(ret);
5391 5392
            ret = NULL;
        }
5393
    }
5394

5395
    virNodeDeviceObjEndAPI(&obj);
5396 5397 5398 5399
    return ret;
}

static char *
5400
testNodeDeviceGetXMLDesc(virNodeDevicePtr dev,
E
Eric Blake 已提交
5401
                         unsigned int flags)
5402
{
5403
    testDriverPtr driver = dev->conn->privateData;
5404 5405 5406
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

E
Eric Blake 已提交
5407 5408
    virCheckFlags(0, NULL);

5409
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5410
        return NULL;
5411

5412
    ret = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(obj));
5413

5414
    virNodeDeviceObjEndAPI(&obj);
5415 5416 5417 5418 5419 5420
    return ret;
}

static char *
testNodeDeviceGetParent(virNodeDevicePtr dev)
{
5421
    testDriverPtr driver = dev->conn->privateData;
5422
    virNodeDeviceObjPtr obj;
5423
    virNodeDeviceDefPtr def;
5424 5425
    char *ret = NULL;

5426
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5427
        return NULL;
5428
    def = virNodeDeviceObjGetDef(obj);
5429

5430 5431
    if (def->parent) {
        ignore_value(VIR_STRDUP(ret, def->parent));
5432
    } else {
5433 5434
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no parent for this device"));
5435 5436
    }

5437
    virNodeDeviceObjEndAPI(&obj);
5438 5439 5440
    return ret;
}

5441

5442 5443 5444
static int
testNodeDeviceNumOfCaps(virNodeDevicePtr dev)
{
5445
    testDriverPtr driver = dev->conn->privateData;
5446
    virNodeDeviceObjPtr obj;
5447
    virNodeDeviceDefPtr def;
5448 5449 5450
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;

5451
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5452
        return -1;
5453
    def = virNodeDeviceObjGetDef(obj);
5454

5455
    for (caps = def->caps; caps; caps = caps->next)
5456 5457
        ++ncaps;

5458
    virNodeDeviceObjEndAPI(&obj);
5459
    return ncaps;
5460 5461 5462 5463 5464 5465
}


static int
testNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
5466
    testDriverPtr driver = dev->conn->privateData;
5467
    virNodeDeviceObjPtr obj;
5468
    virNodeDeviceDefPtr def;
5469 5470 5471
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;

5472
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5473
        return -1;
5474
    def = virNodeDeviceObjGetDef(obj);
5475

5476
    for (caps = def->caps; caps && ncaps < maxnames; caps = caps->next) {
5477 5478 5479 5480
        if (VIR_STRDUP(names[ncaps],
                       virNodeDevCapTypeToString(caps->data.type)) < 0)
            goto error;
        ncaps++;
5481 5482
    }

5483
    virNodeDeviceObjEndAPI(&obj);
5484 5485 5486 5487 5488
    return ncaps;

 error:
    while (--ncaps >= 0)
        VIR_FREE(names[ncaps]);
5489
    virNodeDeviceObjEndAPI(&obj);
5490
    return -1;
5491 5492
}

5493

5494 5495
static virNodeDeviceObjPtr
testNodeDeviceMockCreateVport(testDriverPtr driver,
5496
                              const char *wwnn,
5497
                              const char *wwpn)
5498
{
5499 5500
    char *xml = NULL;
    virNodeDeviceDefPtr def = NULL;
5501
    virNodeDevCapsDefPtr caps;
5502
    virNodeDeviceObjPtr obj = NULL, objcopy = NULL;
5503
    virNodeDeviceDefPtr objdef;
5504
    virObjectEventPtr event = NULL;
5505

5506 5507 5508 5509 5510 5511 5512 5513 5514
    /* 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. */
5515 5516
    if (!(objcopy = virNodeDeviceObjListFindByName(driver->devs,
                                                   "scsi_host11")))
5517 5518
        goto cleanup;

5519
    xml = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(objcopy));
5520
    virNodeDeviceObjEndAPI(&objcopy);
5521 5522 5523 5524
    if (!xml)
        goto cleanup;

    if (!(def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL)))
5525 5526
        goto cleanup;

5527
    VIR_FREE(def->name);
5528
    if (VIR_STRDUP(def->name, "scsi_host12") < 0)
5529 5530
        goto cleanup;

5531 5532 5533
    /* 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. */
5534 5535
    caps = def->caps;
    while (caps) {
5536
        if (caps->data.type != VIR_NODE_DEV_CAP_SCSI_HOST)
5537 5538
            continue;

5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552
        /* 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++;
        }
5553 5554 5555
        caps = caps->next;
    }

5556
    if (!(obj = virNodeDeviceObjListAssignDef(driver->devs, def)))
5557
        goto cleanup;
5558
    def = NULL;
5559
    objdef = virNodeDeviceObjGetDef(obj);
5560

5561
    event = virNodeDeviceEventLifecycleNew(objdef->name,
5562 5563
                                           VIR_NODE_DEVICE_EVENT_CREATED,
                                           0);
5564 5565 5566
    testObjectEventQueue(driver, event);

 cleanup:
5567
    VIR_FREE(xml);
5568 5569
    virNodeDeviceDefFree(def);
    return obj;
5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580
}


static virNodeDevicePtr
testNodeDeviceCreateXML(virConnectPtr conn,
                        const char *xmlDesc,
                        unsigned int flags)
{
    testDriverPtr driver = conn->privateData;
    virNodeDeviceDefPtr def = NULL;
    char *wwnn = NULL, *wwpn = NULL;
5581 5582
    virNodeDevicePtr dev = NULL, ret = NULL;
    virNodeDeviceObjPtr obj = NULL;
5583
    virNodeDeviceDefPtr objdef;
5584 5585 5586 5587 5588 5589

    virCheckFlags(0, NULL);

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

5590 5591 5592
    /* We run this simply for validation - it essentially validates that
     * the input XML either has a wwnn/wwpn or virNodeDevCapSCSIHostParseXML
     * generated a wwnn/wwpn */
5593 5594 5595
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) < 0)
        goto cleanup;

5596 5597 5598
    /* 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. */
5599
    if (virNodeDeviceObjListGetParentHost(driver->devs, def) < 0)
5600 5601 5602 5603
        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
5604 5605 5606
     * 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 */
5607 5608
    if (!(obj = testNodeDeviceMockCreateVport(driver, wwnn, wwpn)))
        goto cleanup;
5609
    objdef = virNodeDeviceObjGetDef(obj);
5610

5611
    if (!(dev = virGetNodeDevice(conn, objdef->name)))
5612 5613
        goto cleanup;

5614 5615
    VIR_FREE(dev->parentName);
    if (VIR_STRDUP(dev->parentName, def->parent) < 0)
5616 5617 5618 5619
        goto cleanup;

    ret = dev;
    dev = NULL;
5620

5621
 cleanup:
5622
    virNodeDeviceObjEndAPI(&obj);
5623
    virNodeDeviceDefFree(def);
5624
    virObjectUnref(dev);
5625 5626
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
5627
    return ret;
5628 5629 5630 5631 5632 5633
}

static int
testNodeDeviceDestroy(virNodeDevicePtr dev)
{
    int ret = 0;
5634
    testDriverPtr driver = dev->conn->privateData;
5635
    virNodeDeviceObjPtr obj = NULL;
5636
    virNodeDeviceObjPtr parentobj = NULL;
5637
    virNodeDeviceDefPtr def;
5638
    char *wwnn = NULL, *wwpn = NULL;
5639
    virObjectEventPtr event = NULL;
5640

5641
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5642
        return -1;
5643
    def = virNodeDeviceObjGetDef(obj);
5644

5645
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) == -1)
5646
        goto cleanup;
5647

5648 5649 5650 5651
    /* Unlike the real code we cannot run into the udevAddOneDevice race
     * which would replace obj->def, so no need to save off the parent,
     * but do need to drop the @obj lock so that the FindByName code doesn't
     * deadlock on ourselves */
5652
    virObjectUnlock(obj);
5653

5654 5655 5656 5657 5658 5659
    /* We do this just for basic validation and throw away the parentobj
     * since there's no vport_delete to be run */
    if (!(parentobj = virNodeDeviceObjListFindByName(driver->devs,
                                                     def->parent))) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("cannot find parent '%s' definition"), def->parent);
5660
        virObjectLock(obj);
5661
        goto cleanup;
5662
    }
5663
    virNodeDeviceObjEndAPI(&parentobj);
5664

5665 5666 5667 5668
    event = virNodeDeviceEventLifecycleNew(dev->name,
                                           VIR_NODE_DEVICE_EVENT_DELETED,
                                           0);

5669
    virObjectLock(obj);
5670
    virNodeDeviceObjListRemove(driver->devs, obj);
5671
    virObjectUnref(obj);
5672
    obj = NULL;
5673

5674
 cleanup:
5675
    virNodeDeviceObjEndAPI(&obj);
5676
    testObjectEventQueue(driver, event);
5677 5678 5679 5680 5681
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return ret;
}

5682 5683

/* Domain event implementations */
5684
static int
5685 5686 5687 5688
testConnectDomainEventRegister(virConnectPtr conn,
                               virConnectDomainEventCallback callback,
                               void *opaque,
                               virFreeCallback freecb)
5689
{
5690
    testDriverPtr driver = conn->privateData;
5691
    int ret = 0;
5692

5693
    if (virDomainEventStateRegister(conn, driver->eventState,
5694 5695
                                    callback, opaque, freecb) < 0)
        ret = -1;
5696 5697 5698 5699

    return ret;
}

5700

5701
static int
5702 5703
testConnectDomainEventDeregister(virConnectPtr conn,
                                 virConnectDomainEventCallback callback)
5704
{
5705
    testDriverPtr driver = conn->privateData;
5706
    int ret = 0;
5707

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

    return ret;
}

5715 5716

static int
5717 5718 5719 5720 5721 5722
testConnectDomainEventRegisterAny(virConnectPtr conn,
                                  virDomainPtr dom,
                                  int eventID,
                                  virConnectDomainEventGenericCallback callback,
                                  void *opaque,
                                  virFreeCallback freecb)
5723
{
5724
    testDriverPtr driver = conn->privateData;
5725 5726
    int ret;

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

    return ret;
}

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

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

    return ret;
}


5750 5751 5752 5753 5754 5755 5756 5757
static int
testConnectNetworkEventRegisterAny(virConnectPtr conn,
                                   virNetworkPtr net,
                                   int eventID,
                                   virConnectNetworkEventGenericCallback callback,
                                   void *opaque,
                                   virFreeCallback freecb)
{
5758
    testDriverPtr driver = conn->privateData;
5759 5760
    int ret;

5761
    if (virNetworkEventStateRegisterID(conn, driver->eventState,
5762
                                       net, eventID, callback,
5763 5764 5765 5766 5767 5768 5769 5770 5771 5772
                                       opaque, freecb, &ret) < 0)
        ret = -1;

    return ret;
}

static int
testConnectNetworkEventDeregisterAny(virConnectPtr conn,
                                     int callbackID)
{
5773
    testDriverPtr driver = conn->privateData;
5774
    int ret = 0;
5775

5776
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5777
                                        callbackID, true) < 0)
5778
        ret = -1;
5779 5780 5781 5782

    return ret;
}

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
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,
5810
                                        callbackID, true) < 0)
5811 5812 5813 5814 5815
        ret = -1;

    return ret;
}

5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842
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,
5843
                                        callbackID, true) < 0)
5844 5845 5846 5847 5848
        ret = -1;

    return ret;
}

5849 5850 5851
static int testConnectListAllDomains(virConnectPtr conn,
                                     virDomainPtr **domains,
                                     unsigned int flags)
5852
{
5853
    testDriverPtr privconn = conn->privateData;
5854

O
Osier Yang 已提交
5855
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
5856

5857 5858
    return virDomainObjListExport(privconn->domains, conn, domains,
                                  NULL, flags);
5859 5860
}

5861
static int
P
Peter Krempa 已提交
5862
testNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,
5863 5864 5865 5866 5867 5868 5869
                  unsigned char **cpumap,
                  unsigned int *online,
                  unsigned int flags)
{
    virCheckFlags(0, -1);

    if (cpumap) {
5870
        if (VIR_ALLOC_N(*cpumap, 1) < 0)
P
Peter Krempa 已提交
5871
            return -1;
5872 5873 5874 5875 5876 5877
        *cpumap[0] = 0x15;
    }

    if (online)
        *online = 3;

P
Peter Krempa 已提交
5878
    return  8;
5879 5880
}

5881 5882 5883 5884 5885 5886 5887 5888 5889 5890
static char *
testDomainScreenshot(virDomainPtr dom ATTRIBUTE_UNUSED,
                     virStreamPtr st,
                     unsigned int screen ATTRIBUTE_UNUSED,
                     unsigned int flags)
{
    char *ret = NULL;

    virCheckFlags(0, NULL);

5891
    if (VIR_STRDUP(ret, "image/png") < 0)
5892 5893
        return NULL;

D
Daniel P. Berrange 已提交
5894
    if (virFDStreamOpenFile(st, PKGDATADIR "/test-screenshot.png", 0, 0, O_RDONLY) < 0)
5895 5896 5897 5898 5899
        VIR_FREE(ret);

    return ret;
}

5900 5901
static int
testConnectGetCPUModelNames(virConnectPtr conn ATTRIBUTE_UNUSED,
J
Jiri Denemark 已提交
5902
                            const char *archName,
5903 5904 5905
                            char ***models,
                            unsigned int flags)
{
J
Jiri Denemark 已提交
5906 5907
    virArch arch;

5908
    virCheckFlags(0, -1);
J
Jiri Denemark 已提交
5909 5910 5911 5912 5913 5914 5915 5916

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

J
Jiri Denemark 已提交
5917
    return virCPUGetModels(arch, models);
5918
}
5919

C
Cole Robinson 已提交
5920 5921 5922
static int
testDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
5923
    testDriverPtr privconn = dom->conn->privateData;
C
Cole Robinson 已提交
5924
    virDomainObjPtr vm = NULL;
5925
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
5926 5927 5928 5929 5930 5931
    int ret = -1;

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

5932 5933
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5934

5935
    if (virDomainObjCheckActive(vm) < 0)
C
Cole Robinson 已提交
5936 5937 5938 5939 5940 5941 5942 5943 5944
        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);
5945
    event = virDomainEventLifecycleNewFromObj(vm,
C
Cole Robinson 已提交
5946 5947 5948 5949 5950
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
    vm->hasManagedSave = true;

    ret = 0;
5951
 cleanup:
5952
    virDomainObjEndAPI(&vm);
5953
    testObjectEventQueue(privconn, event);
C
Cole Robinson 已提交
5954 5955 5956 5957 5958 5959 5960 5961 5962

    return ret;
}


static int
testDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm;
5963
    int ret;
C
Cole Robinson 已提交
5964 5965 5966

    virCheckFlags(0, -1);

5967 5968
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5969 5970

    ret = vm->hasManagedSave;
5971

5972
    virDomainObjEndAPI(&vm);
C
Cole Robinson 已提交
5973 5974 5975 5976 5977 5978 5979 5980 5981 5982
    return ret;
}

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

    virCheckFlags(0, -1);

5983 5984
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5985 5986

    vm->hasManagedSave = false;
5987

5988
    virDomainObjEndAPI(&vm);
5989
    return 0;
C
Cole Robinson 已提交
5990 5991 5992
}


5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026
/*
 * 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;
6027
    int n;
6028 6029 6030 6031 6032

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6033
        return -1;
6034 6035 6036

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

6037
    virDomainObjEndAPI(&vm);
6038 6039 6040 6041 6042 6043 6044 6045 6046 6047
    return n;
}

static int
testDomainSnapshotListNames(virDomainPtr domain,
                            char **names,
                            int nameslen,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6048
    int n;
6049 6050 6051 6052 6053

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6054
        return -1;
6055 6056 6057 6058

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

6059
    virDomainObjEndAPI(&vm);
6060 6061 6062 6063 6064 6065 6066 6067 6068
    return n;
}

static int
testDomainListAllSnapshots(virDomainPtr domain,
                           virDomainSnapshotPtr **snaps,
                           unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6069
    int n;
6070 6071 6072 6073 6074

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6075
        return -1;
6076 6077 6078

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

6079
    virDomainObjEndAPI(&vm);
6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096
    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)))
6097
        return -1;
6098 6099 6100 6101 6102 6103 6104

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

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

6105
 cleanup:
6106
    virDomainObjEndAPI(&vm);
6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121
    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)))
6122
        return -1;
6123 6124 6125 6126 6127 6128

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

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

6129
 cleanup:
6130
    virDomainObjEndAPI(&vm);
6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146
    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)))
6147
        return -1;
6148 6149 6150 6151 6152 6153 6154

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

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

6155
 cleanup:
6156
    virDomainObjEndAPI(&vm);
6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171
    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)))
6172
        return NULL;
6173 6174 6175 6176 6177 6178

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

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

6179
 cleanup:
6180
    virDomainObjEndAPI(&vm);
6181 6182 6183 6184 6185 6186 6187 6188
    return snapshot;
}

static int
testDomainHasCurrentSnapshot(virDomainPtr domain,
                             unsigned int flags)
{
    virDomainObjPtr vm;
6189
    int ret;
6190 6191 6192 6193

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6194
        return -1;
6195 6196 6197

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

6198
    virDomainObjEndAPI(&vm);
6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212
    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)))
6213
        return NULL;
6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226

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

6227
 cleanup:
6228
    virDomainObjEndAPI(&vm);
6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241
    return parent;
}

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

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
6242
        return NULL;
6243 6244 6245 6246 6247 6248 6249 6250 6251

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

6252
 cleanup:
6253
    virDomainObjEndAPI(&vm);
6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264
    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];
6265
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6266 6267 6268 6269

    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6270
        return NULL;
6271 6272 6273 6274 6275 6276

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

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

6277
    xml = virDomainSnapshotDefFormat(uuidstr, snap->def, privconn->caps,
6278
                                     privconn->xmlopt,
6279 6280
                                     virDomainDefFormatConvertXMLFlags(flags),
                                     0);
6281

6282
 cleanup:
6283
    virDomainObjEndAPI(&vm);
6284 6285 6286 6287 6288 6289 6290 6291
    return xml;
}

static int
testDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6292
    int ret;
6293 6294 6295 6296

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6297
        return -1;
6298 6299 6300 6301

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

6302
    virDomainObjEndAPI(&vm);
6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316
    return ret;
}


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

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6317
        return -1;
6318

C
Cole Robinson 已提交
6319
    if (!testSnapObjFromSnapshot(vm, snapshot))
6320 6321 6322 6323
        goto cleanup;

    ret = 1;

6324
 cleanup:
6325
    virDomainObjEndAPI(&vm);
6326 6327 6328
    return ret;
}

6329 6330 6331 6332 6333 6334
static int
testDomainSnapshotAlignDisks(virDomainObjPtr vm,
                             virDomainSnapshotDefPtr def,
                             unsigned int flags)
{
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
E
Eric Blake 已提交
6335
    bool align_match = true;
6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363

    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)
{
6364
    testDriverPtr privconn = domain->conn->privateData;
6365 6366 6367 6368
    virDomainObjPtr vm = NULL;
    virDomainSnapshotDefPtr def = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr snapshot = NULL;
6369
    virObjectEventPtr event = NULL;
6370
    char *xml = NULL;
6371 6372
    bool update_current = true;
    bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
6373 6374 6375 6376 6377 6378 6379 6380
    unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;

    /*
     * DISK_ONLY: Not implemented yet
     * REUSE_EXT: Not implemented yet
     *
     * NO_METADATA: Explicitly not implemented
     *
6381
     * REDEFINE + CURRENT: Implemented
6382 6383 6384 6385 6386 6387
     * HALT: Implemented
     * QUIESCE: Nothing to do
     * ATOMIC: Nothing to do
     * LIVE: Nothing to do
     */
    virCheckFlags(
6388 6389
        VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
        VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
6390 6391 6392 6393 6394
        VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
        VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
        VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
        VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, NULL);

6395 6396 6397 6398 6399
    if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)))
        update_current = false;
    if (redefine)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;

6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414
    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;

6415
    if (redefine) {
C
Cole Robinson 已提交
6416
        if (virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
6417
                                          privconn->xmlopt,
C
Cole Robinson 已提交
6418
                                          &update_current, flags) < 0)
6419 6420 6421 6422 6423
            goto cleanup;
    } else {
        if (!(def->dom = virDomainDefCopy(vm->def,
                                          privconn->caps,
                                          privconn->xmlopt,
6424
                                          NULL,
6425 6426
                                          true)))
            goto cleanup;
6427

6428
        if (testDomainSnapshotAlignDisks(vm, def, flags) < 0)
6429 6430 6431
            goto cleanup;
    }

6432 6433 6434 6435
    if (!snap) {
        if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
            goto cleanup;
        def = NULL;
6436 6437
    }

6438 6439 6440 6441 6442 6443 6444 6445 6446 6447
    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);
6448
            event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
6449 6450 6451
                                    VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
        }
    }
6452 6453

    snapshot = virGetDomainSnapshot(domain, snap->def->name);
6454
 cleanup:
6455 6456 6457 6458
    VIR_FREE(xml);
    if (vm) {
        if (snapshot) {
            virDomainSnapshotObjPtr other;
6459 6460
            if (update_current)
                vm->current_snapshot = snap;
6461 6462 6463 6464 6465 6466 6467
            other = virDomainSnapshotFindByName(vm->snapshots,
                                                snap->def->parent);
            snap->parent = other;
            other->nchildren++;
            snap->sibling = other->first_child;
            other->first_child = snap;
        }
6468
        virDomainObjEndAPI(&vm);
6469
    }
6470
    testObjectEventQueue(privconn, event);
6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482
    virDomainSnapshotDefFree(def);
    return snapshot;
}


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

6483
static int
6484
testDomainSnapshotDiscardAll(void *payload,
6485 6486
                             const void *name ATTRIBUTE_UNUSED,
                             void *data)
6487 6488 6489 6490 6491 6492 6493
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapRemoveDataPtr curr = data;

    if (snap->def->current)
        curr->current = true;
    virDomainSnapshotObjListRemove(curr->vm->snapshots, snap);
6494
    return 0;
6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505
}

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

6506
static int
6507 6508 6509 6510 6511 6512 6513
testDomainSnapshotReparentChildren(void *payload,
                                   const void *name ATTRIBUTE_UNUSED,
                                   void *data)
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapReparentDataPtr rep = data;

6514
    if (rep->err < 0)
6515
        return 0;
6516 6517 6518 6519 6520 6521 6522

    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;
6523
        return 0;
6524 6525 6526 6527
    }

    if (!snap->sibling)
        rep->last = snap;
6528
    return 0;
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
}

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) {
6558
            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)
6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601
                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;
6602
 cleanup:
6603
    virDomainObjEndAPI(&vm);
6604 6605 6606 6607 6608 6609 6610
    return ret;
}

static int
testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                           unsigned int flags)
{
6611
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6612 6613
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
6614 6615
    virObjectEventPtr event = NULL;
    virObjectEventPtr event2 = NULL;
6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678
    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;
6679 6680
    config = virDomainDefCopy(snap->def->dom, privconn->caps,
                              privconn->xmlopt, NULL, true);
6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692
    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.  */
6693 6694
            if (!virDomainDefCheckABIStability(vm->def, config,
                                               privconn->xmlopt)) {
6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707
                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);
6708
                event = virDomainEventLifecycleNewFromObj(vm,
6709 6710
                            VIR_DOMAIN_EVENT_STOPPED,
                            VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
6711
                testObjectEventQueue(privconn, event);
6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722
                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. */
6723
                event = virDomainEventLifecycleNewFromObj(vm,
6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736
                                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;
6737
            event = virDomainEventLifecycleNewFromObj(vm,
6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750
                                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 */
6751
                event2 = virDomainEventLifecycleNewFromObj(vm,
6752 6753 6754 6755 6756
                                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 已提交
6757
            virObjectUnref(event);
6758 6759 6760 6761
            event = NULL;

            if (was_stopped) {
                /* Transition 2 */
6762
                event = virDomainEventLifecycleNewFromObj(vm,
6763 6764 6765 6766
                                VIR_DOMAIN_EVENT_STARTED,
                                VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            } else if (was_running) {
                /* Transition 8 */
6767
                event = virDomainEventLifecycleNewFromObj(vm,
6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779
                                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);
6780
            event = virDomainEventLifecycleNewFromObj(vm,
6781 6782 6783 6784 6785 6786 6787 6788 6789
                                    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;

6790
            testObjectEventQueue(privconn, event);
6791
            event = virDomainEventLifecycleNewFromObj(vm,
6792 6793 6794
                            VIR_DOMAIN_EVENT_STARTED,
                            VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            if (paused) {
6795
                event2 = virDomainEventLifecycleNewFromObj(vm,
6796 6797 6798 6799 6800 6801 6802 6803
                                VIR_DOMAIN_EVENT_SUSPENDED,
                                VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
            }
        }
    }

    vm->current_snapshot = snap;
    ret = 0;
6804
 cleanup:
6805
    if (event) {
6806
        testObjectEventQueue(privconn, event);
6807
        testObjectEventQueue(privconn, event2);
C
Cole Robinson 已提交
6808
    } else {
C
Cédric Bosdonnat 已提交
6809
        virObjectUnref(event2);
6810
    }
6811
    virDomainObjEndAPI(&vm);
6812 6813 6814 6815 6816

    return ret;
}


6817

6818
static virHypervisorDriver testHypervisorDriver = {
6819
    .name = "Test",
6820 6821 6822
    .connectOpen = testConnectOpen, /* 0.1.1 */
    .connectClose = testConnectClose, /* 0.1.1 */
    .connectGetVersion = testConnectGetVersion, /* 0.1.1 */
6823
    .connectGetHostname = testConnectGetHostname, /* 0.6.3 */
6824
    .connectGetMaxVcpus = testConnectGetMaxVcpus, /* 0.3.2 */
6825
    .nodeGetInfo = testNodeGetInfo, /* 0.1.1 */
6826
    .nodeGetCPUStats = testNodeGetCPUStats, /* 2.3.0 */
6827
    .nodeGetFreeMemory = testNodeGetFreeMemory, /* 2.3.0 */
6828
    .nodeGetFreePages = testNodeGetFreePages, /* 2.3.0 */
6829
    .connectGetCapabilities = testConnectGetCapabilities, /* 0.2.1 */
6830
    .connectGetSysinfo = testConnectGetSysinfo, /* 2.3.0 */
6831
    .connectGetType = testConnectGetType, /* 2.3.0 */
6832 6833 6834
    .connectListDomains = testConnectListDomains, /* 0.1.1 */
    .connectNumOfDomains = testConnectNumOfDomains, /* 0.1.1 */
    .connectListAllDomains = testConnectListAllDomains, /* 0.9.13 */
6835
    .domainCreateXML = testDomainCreateXML, /* 0.1.4 */
6836 6837 6838 6839 6840 6841 6842 6843 6844
    .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 */
6845
    .domainDestroyFlags = testDomainDestroyFlags, /* 4.2.0 */
6846 6847 6848 6849 6850
    .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 */
6851 6852
    .domainGetState = testDomainGetState, /* 0.9.2 */
    .domainSave = testDomainSave, /* 0.3.2 */
6853
    .domainSaveFlags = testDomainSaveFlags, /* 0.9.4 */
6854
    .domainRestore = testDomainRestore, /* 0.3.2 */
6855
    .domainRestoreFlags = testDomainRestoreFlags, /* 0.9.4 */
6856
    .domainCoreDump = testDomainCoreDump, /* 0.3.2 */
6857
    .domainCoreDumpWithFormat = testDomainCoreDumpWithFormat, /* 1.2.3 */
6858
    .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */
6859 6860 6861 6862
    .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */
    .domainGetVcpusFlags = testDomainGetVcpusFlags, /* 0.8.5 */
    .domainPinVcpu = testDomainPinVcpu, /* 0.7.3 */
    .domainGetVcpus = testDomainGetVcpus, /* 0.7.3 */
6863
    .domainGetVcpuPinInfo = testDomainGetVcpuPinInfo, /* 1.2.18 */
6864 6865
    .domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
    .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
6866 6867
    .connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
    .connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
6868 6869 6870
    .domainCreate = testDomainCreate, /* 0.1.11 */
    .domainCreateWithFlags = testDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = testDomainDefineXML, /* 0.1.11 */
6871
    .domainDefineXMLFlags = testDomainDefineXMLFlags, /* 1.2.12 */
6872
    .domainUndefine = testDomainUndefine, /* 0.1.11 */
6873
    .domainUndefineFlags = testDomainUndefineFlags, /* 0.9.4 */
6874 6875 6876
    .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
    .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
    .domainGetSchedulerType = testDomainGetSchedulerType, /* 0.3.2 */
6877 6878 6879 6880
    .domainGetSchedulerParameters = testDomainGetSchedulerParameters, /* 0.3.2 */
    .domainGetSchedulerParametersFlags = testDomainGetSchedulerParametersFlags, /* 0.9.2 */
    .domainSetSchedulerParameters = testDomainSetSchedulerParameters, /* 0.3.2 */
    .domainSetSchedulerParametersFlags = testDomainSetSchedulerParametersFlags, /* 0.9.2 */
6881 6882 6883
    .domainBlockStats = testDomainBlockStats, /* 0.7.0 */
    .domainInterfaceStats = testDomainInterfaceStats, /* 0.7.0 */
    .nodeGetCellsFreeMemory = testNodeGetCellsFreeMemory, /* 0.4.2 */
6884 6885 6886 6887
    .connectDomainEventRegister = testConnectDomainEventRegister, /* 0.6.0 */
    .connectDomainEventDeregister = testConnectDomainEventDeregister, /* 0.6.0 */
    .connectIsEncrypted = testConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = testConnectIsSecure, /* 0.7.3 */
6888 6889 6890
    .domainIsActive = testDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = testDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = testDomainIsUpdated, /* 0.8.6 */
6891 6892 6893
    .connectDomainEventRegisterAny = testConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = testConnectDomainEventDeregisterAny, /* 0.8.0 */
    .connectIsAlive = testConnectIsAlive, /* 0.9.8 */
6894
    .nodeGetCPUMap = testNodeGetCPUMap, /* 1.0.0 */
6895
    .domainRename = testDomainRename, /* 4.1.0 */
6896
    .domainScreenshot = testDomainScreenshot, /* 1.0.5 */
6897 6898
    .domainGetMetadata = testDomainGetMetadata, /* 1.1.3 */
    .domainSetMetadata = testDomainSetMetadata, /* 1.1.3 */
6899
    .connectGetCPUModelNames = testConnectGetCPUModelNames, /* 1.1.3 */
6900 6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916
    .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 */
6917 6918 6919
    .domainSnapshotCreateXML = testDomainSnapshotCreateXML, /* 1.1.4 */
    .domainRevertToSnapshot = testDomainRevertToSnapshot, /* 1.1.4 */
    .domainSnapshotDelete = testDomainSnapshotDelete, /* 1.1.4 */
6920

E
Eric Blake 已提交
6921
    .connectBaselineCPU = testConnectBaselineCPU, /* 1.2.0 */
6922 6923 6924
};

static virNetworkDriver testNetworkDriver = {
6925 6926 6927 6928 6929
    .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 */
6930 6931
    .connectNetworkEventRegisterAny = testConnectNetworkEventRegisterAny, /* 1.2.1 */
    .connectNetworkEventDeregisterAny = testConnectNetworkEventDeregisterAny, /* 1.2.1 */
6932 6933 6934 6935
    .networkLookupByUUID = testNetworkLookupByUUID, /* 0.3.2 */
    .networkLookupByName = testNetworkLookupByName, /* 0.3.2 */
    .networkCreateXML = testNetworkCreateXML, /* 0.3.2 */
    .networkDefineXML = testNetworkDefineXML, /* 0.3.2 */
6936
    .networkUndefine = testNetworkUndefine, /* 0.3.2 */
6937
    .networkUpdate = testNetworkUpdate, /* 0.10.2 */
6938
    .networkCreate = testNetworkCreate, /* 0.3.2 */
6939 6940 6941 6942 6943 6944 6945
    .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 */
6946 6947
};

L
Laine Stump 已提交
6948
static virInterfaceDriver testInterfaceDriver = {
6949 6950 6951 6952 6953 6954
    .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 */
6955 6956 6957 6958 6959 6960
    .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 */
6961 6962 6963
    .interfaceChangeBegin = testInterfaceChangeBegin,   /* 0.9.2 */
    .interfaceChangeCommit = testInterfaceChangeCommit,  /* 0.9.2 */
    .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */
L
Laine Stump 已提交
6964 6965 6966
};


6967
static virStorageDriver testStorageDriver = {
6968 6969 6970 6971 6972 6973
    .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 */
6974 6975
    .connectStoragePoolEventRegisterAny = testConnectStoragePoolEventRegisterAny, /* 2.0.0 */
    .connectStoragePoolEventDeregisterAny = testConnectStoragePoolEventDeregisterAny, /* 2.0.0 */
6976 6977 6978
    .storagePoolLookupByName = testStoragePoolLookupByName, /* 0.5.0 */
    .storagePoolLookupByUUID = testStoragePoolLookupByUUID, /* 0.5.0 */
    .storagePoolLookupByVolume = testStoragePoolLookupByVolume, /* 0.5.0 */
6979 6980
    .storagePoolCreateXML = testStoragePoolCreateXML, /* 0.5.0 */
    .storagePoolDefineXML = testStoragePoolDefineXML, /* 0.5.0 */
6981 6982
    .storagePoolBuild = testStoragePoolBuild, /* 0.5.0 */
    .storagePoolUndefine = testStoragePoolUndefine, /* 0.5.0 */
6983
    .storagePoolCreate = testStoragePoolCreate, /* 0.5.0 */
6984 6985 6986 6987 6988 6989 6990
    .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 */
6991
    .storagePoolNumOfVolumes = testStoragePoolNumOfVolumes, /* 0.5.0 */
6992 6993 6994
    .storagePoolListVolumes = testStoragePoolListVolumes, /* 0.5.0 */
    .storagePoolListAllVolumes = testStoragePoolListAllVolumes, /* 0.10.2 */

6995 6996 6997 6998 6999 7000 7001 7002 7003
    .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 */
7004 7005
    .storagePoolIsActive = testStoragePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = testStoragePoolIsPersistent, /* 0.7.3 */
7006 7007
};

7008
static virNodeDeviceDriver testNodeDeviceDriver = {
7009 7010
    .connectNodeDeviceEventRegisterAny = testConnectNodeDeviceEventRegisterAny, /* 2.2.0 */
    .connectNodeDeviceEventDeregisterAny = testConnectNodeDeviceEventDeregisterAny, /* 2.2.0 */
7011 7012 7013 7014 7015 7016 7017 7018 7019
    .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 */
7020 7021
};

7022
static virConnectDriver testConnectDriver = {
7023
    .localOnly = true,
7024
    .uriSchemes = (const char *[]){ "test", NULL },
7025 7026 7027 7028 7029 7030 7031
    .hypervisorDriver = &testHypervisorDriver,
    .interfaceDriver = &testInterfaceDriver,
    .networkDriver = &testNetworkDriver,
    .nodeDeviceDriver = &testNodeDeviceDriver,
    .nwfilterDriver = NULL,
    .secretDriver = NULL,
    .storageDriver = &testStorageDriver,
7032 7033
};

7034 7035 7036 7037 7038 7039 7040 7041
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
7042 7043
    return virRegisterConnectDriver(&testConnectDriver,
                                    false);
7044
}