test_driver.c 197.3 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
#include <config.h>
23

24
#include <sys/time.h>
25 26
#include <fcntl.h>
#include <unistd.h>
27
#include <sys/stat.h>
C
Cole Robinson 已提交
28
#include <libxml/xmlsave.h>
29
#include <libxml/xpathInternals.h>
30

31

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

67 68
#define VIR_FROM_THIS VIR_FROM_TEST

69 70
VIR_LOG_INIT("test.test_driver");

71

72 73 74 75
#define MAX_CPUS 128

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

#define MAX_CELLS 128
84

85 86 87 88 89 90 91
struct _testAuth {
    char *username;
    char *password;
};
typedef struct _testAuth testAuth;
typedef struct _testAuth *testAuthPtr;

92
struct _testDriver {
93
    virObjectLockable parent;
94

95
    virNodeInfo nodeInfo;
96
    virInterfaceObjListPtr ifaces;
97
    bool transaction_running;
98
    virInterfaceObjListPtr backupIfaces;
99
    virStoragePoolObjListPtr pools;
100
    virNodeDeviceObjListPtr devs;
101 102
    int numCells;
    testCell cells[MAX_CELLS];
103 104
    size_t numAuths;
    testAuthPtr auths;
105

106 107 108
    /* virAtomic access only */
    volatile int nextDomID;

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

124
static testDriverPtr defaultPrivconn;
125
static virMutex defaultLock = VIR_MUTEX_INITIALIZER;
126

127 128 129 130 131 132 133 134 135
static virClassPtr testDriverClass;
static void testDriverDispose(void *obj);
static int testDriverOnceInit(void)
{
    if (!(VIR_CLASS_NEW(testDriver, virClassForObjectLockable())))
        return -1;

    return 0;
}
136
VIR_ONCE_GLOBAL_INIT(testDriver);
137

138
#define TEST_MODEL "i686"
139
#define TEST_EMULATOR "/usr/bin/test-hv"
140

141
static const virNodeInfo defaultNodeInfo = {
142
    TEST_MODEL,
143 144 145 146 147 148 149
    1024*1024*3, /* 3 GB */
    16,
    1400,
    2,
    2,
    2,
    2,
150 151
};

152
static void
153
testDriverDispose(void *obj)
154
{
155
    testDriverPtr driver = obj;
156 157 158 159

    virObjectUnref(driver->caps);
    virObjectUnref(driver->xmlopt);
    virObjectUnref(driver->domains);
160
    virNodeDeviceObjListFree(driver->devs);
161
    virObjectUnref(driver->networks);
162
    virObjectUnref(driver->ifaces);
163
    virObjectUnref(driver->pools);
164
    virObjectUnref(driver->eventState);
165 166
}

167 168 169 170 171 172
#define TEST_NAMESPACE_HREF "http://libvirt.org/schemas/domain/test/1.0"

typedef struct _testDomainNamespaceDef testDomainNamespaceDef;
typedef testDomainNamespaceDef *testDomainNamespaceDefPtr;
struct _testDomainNamespaceDef {
    int runstate;
173
    bool transient;
C
Cole Robinson 已提交
174
    bool hasManagedSave;
175 176 177

    unsigned int num_snap_nodes;
    xmlNodePtr *snap_nodes;
178 179 180 181 182 183
};

static void
testDomainDefNamespaceFree(void *data)
{
    testDomainNamespaceDefPtr nsdata = data;
184 185 186 187 188 189 190 191 192
    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);
193 194 195 196 197 198 199 200 201 202
    VIR_FREE(nsdata);
}

static int
testDomainDefNamespaceParse(xmlDocPtr xml ATTRIBUTE_UNUSED,
                            xmlNodePtr root ATTRIBUTE_UNUSED,
                            xmlXPathContextPtr ctxt,
                            void **data)
{
    testDomainNamespaceDefPtr nsdata = NULL;
203 204
    int tmp, n;
    size_t i;
205
    unsigned int tmpuint;
206
    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
207 208 209 210 211 212 213 214 215 216 217 218

    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;

219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
    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++;
    }

237 238 239 240 241 242 243
    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 已提交
244 245 246 247 248 249 250
    tmp = virXPathBoolean("boolean(./test:hasmanagedsave)", ctxt);
    if (tmp == -1) {
        virReportError(VIR_ERR_XML_ERROR, "%s", _("invalid hasmanagedsave"));
        goto error;
    }
    nsdata->hasManagedSave = tmp;

251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
    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;
    }

267 268 269 270 271
    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 已提交
272 273 274 275 276
    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;
    }
277

278 279 280
    *data = nsdata;
    return 0;

281
 error:
282 283 284
    testDomainDefNamespaceFree(nsdata);
    return -1;
}
285

286
static virCapsPtr
287 288
testBuildCapabilities(virConnectPtr conn)
{
289
    testDriverPtr privconn = conn->privateData;
290 291
    virCapsPtr caps;
    virCapsGuestPtr guest;
292 293
    int guest_types[] = { VIR_DOMAIN_OSTYPE_HVM,
                          VIR_DOMAIN_OSTYPE_XEN };
294
    size_t i, j;
295

296
    if ((caps = virCapabilitiesNew(VIR_ARCH_I686, false, false)) == NULL)
297
        goto error;
298

299
    if (virCapabilitiesAddHostFeature(caps, "pae") < 0)
300
        goto error;
301
    if (virCapabilitiesAddHostFeature(caps, "nonpae") < 0)
302
        goto error;
303

304 305
    virCapabilitiesHostInitIOMMU(caps);

306
    if (VIR_ALLOC_N(caps->host.pagesSize, 4) < 0)
307 308 309
        goto error;

    caps->host.pagesSize[caps->host.nPagesSize++] = 4;
310
    caps->host.pagesSize[caps->host.nPagesSize++] = 8;
311
    caps->host.pagesSize[caps->host.nPagesSize++] = 2048;
312
    caps->host.pagesSize[caps->host.nPagesSize++] = 1024 * 1024;
313

314
    for (i = 0; i < privconn->numCells; i++) {
315
        virCapsHostNUMACellCPUPtr cpu_cells;
316
        virCapsHostNUMACellPageInfoPtr pages;
317
        size_t nPages = caps->host.nPagesSize - 1;
318

319
        if (VIR_ALLOC_N(cpu_cells, privconn->cells[i].numCpus) < 0 ||
320
            VIR_ALLOC_N(pages, nPages) < 0) {
321 322 323 324
                VIR_FREE(cpu_cells);
                goto error;
            }

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

328 329 330 331 332 333 334
        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];
335 336

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

338
        if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].mem,
339
                                           privconn->cells[i].numCpus,
340
                                           cpu_cells, 0, NULL, nPages, pages) < 0)
341
            goto error;
342 343
    }

344
    for (i = 0; i < ARRAY_CARDINALITY(guest_types); i++) {
345 346
        if ((guest = virCapabilitiesAddGuest(caps,
                                             guest_types[i],
347
                                             VIR_ARCH_I686,
348 349 350 351
                                             TEST_EMULATOR,
                                             NULL,
                                             0,
                                             NULL)) == NULL)
352
            goto error;
353

354
        if (virCapabilitiesAddGuestDomain(guest,
355
                                          VIR_DOMAIN_VIRT_TEST,
356 357 358 359
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
360
            goto error;
361

362
        if (virCapabilitiesAddGuestFeature(guest, "pae", true, true) == NULL)
363
            goto error;
364
        if (virCapabilitiesAddGuestFeature(guest, "nonpae", true, true) == NULL)
365
            goto error;
366 367
    }

368 369
    caps->host.nsecModels = 1;
    if (VIR_ALLOC_N(caps->host.secModels, caps->host.nsecModels) < 0)
370
        goto error;
371 372
    if (VIR_STRDUP(caps->host.secModels[0].model, "testSecurity") < 0)
        goto error;
373

374 375
    if (VIR_STRDUP(caps->host.secModels[0].doi, "") < 0)
        goto error;
376

377
    return caps;
378

379
 error:
380
    virObjectUnref(caps);
381
    return NULL;
382 383
}

384

385 386 387 388 389 390 391 392 393
static testDriverPtr
testDriverNew(void)
{
    virDomainXMLNamespace ns = {
        .parse = testDomainDefNamespaceParse,
        .free = testDomainDefNamespaceFree,
    };
    testDriverPtr ret;

394
    if (testDriverInitialize() < 0)
395 396
        return NULL;

397 398
    if (!(ret = virObjectLockableNew(testDriverClass)))
        return NULL;
399

400
    if (!(ret->xmlopt = virDomainXMLOptionNew(NULL, NULL, &ns, NULL, NULL)) ||
401
        !(ret->eventState = virObjectEventStateNew()) ||
402
        !(ret->ifaces = virInterfaceObjListNew()) ||
403
        !(ret->domains = virDomainObjListNew()) ||
404
        !(ret->networks = virNetworkObjListNew()) ||
405 406
        !(ret->devs = virNodeDeviceObjListNew()) ||
        !(ret->pools = virStoragePoolObjListNew()))
407 408
        goto error;

409
    virAtomicIntSet(&ret->nextDomID, 1);
410 411 412 413

    return ret;

 error:
414
    virObjectUnref(ret);
415 416 417 418
    return NULL;
}


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

C
Cole Robinson 已提交
527

528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
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";

551
static const unsigned long long defaultPoolCap = (100 * 1024 * 1024 * 1024ull);
552
static const unsigned long long defaultPoolAlloc;
C
Cole Robinson 已提交
553

554
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr obj);
555
static int testNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
556

557 558 559 560
static virDomainObjPtr
testDomObjFromDomain(virDomainPtr domain)
{
    virDomainObjPtr vm;
561
    testDriverPtr driver = domain->conn->privateData;
562 563
    char uuidstr[VIR_UUID_STRING_BUFLEN];

564
    vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
565 566 567 568 569 570 571 572 573 574
    if (!vm) {
        virUUIDFormat(domain->uuid, uuidstr);
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching uuid '%s' (%s)"),
                       uuidstr, domain->name);
    }

    return vm;
}

575
static char *
576 577
testDomainGenerateIfname(virDomainDefPtr domdef)
{
578
    int maxif = 1024;
579
    int ifctr;
580 581

    for (ifctr = 0; ifctr < maxif; ++ifctr) {
M
Michal Privoznik 已提交
582
        virDomainNetDefPtr net = NULL;
583 584
        char *ifname;

585
        if (virAsprintf(&ifname, "testnet%d", ifctr) < 0)
586 587 588
            return NULL;

        /* Generate network interface names */
M
Michal Privoznik 已提交
589
        if (!(net = virDomainNetFindByName(domdef, ifname)))
590
            return ifname;
591
        VIR_FREE(ifname);
592 593
    }

594 595
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Exceeded max iface limit %d"), maxif);
596 597 598
    return NULL;
}

599
static int
600
testDomainGenerateIfnames(virDomainDefPtr domdef)
601
{
602
    size_t i = 0;
603 604 605 606 607 608

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

609
        ifname = testDomainGenerateIfname(domdef);
610
        if (!ifname)
611
            return -1;
612 613 614 615

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

616
    return 0;
617 618
}

619

620 621
static void
testDomainShutdownState(virDomainPtr domain,
J
Jiri Denemark 已提交
622 623
                        virDomainObjPtr privdom,
                        virDomainShutoffReason reason)
624
{
625
    virDomainObjRemoveTransientDef(privdom);
J
Jiri Denemark 已提交
626
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF, reason);
627

628 629 630 631
    if (domain)
        domain->id = -1;
}

632
/* Set up domain runtime state */
633
static int
634
testDomainStartState(testDriverPtr privconn,
J
Jiri Denemark 已提交
635 636
                     virDomainObjPtr dom,
                     virDomainRunningReason reason)
637
{
638
    int ret = -1;
639

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

643
    if (virDomainObjSetDefTransient(privconn->caps,
644
                                    privconn->xmlopt,
645
                                    dom) < 0) {
646 647 648
        goto cleanup;
    }

C
Cole Robinson 已提交
649
    dom->hasManagedSave = false;
650
    ret = 0;
651
 cleanup:
652
    if (ret < 0)
J
Jiri Denemark 已提交
653
        testDomainShutdownState(NULL, dom, VIR_DOMAIN_SHUTOFF_FAILED);
654
    return ret;
655
}
656

657

658
static char *testBuildFilename(const char *relativeTo,
659 660
                               const char *filename)
{
661 662
    char *offset;
    int baseLen;
663 664
    char *ret;

665
    if (!filename || filename[0] == '\0')
666
        return NULL;
667 668 669 670
    if (filename[0] == '/') {
        ignore_value(VIR_STRDUP(ret, filename));
        return ret;
    }
671

672
    offset = strrchr(relativeTo, '/');
673
    if ((baseLen = (offset-relativeTo+1))) {
674
        char *absFile;
C
Chris Lalancette 已提交
675 676
        int totalLen = baseLen + strlen(filename) + 1;
        if (VIR_ALLOC_N(absFile, totalLen) < 0)
677
            return NULL;
678
        if (virStrncpy(absFile, relativeTo, baseLen, totalLen) < 0) {
C
Chris Lalancette 已提交
679 680 681
            VIR_FREE(absFile);
            return NULL;
        }
682 683 684
        strcat(absFile, filename);
        return absFile;
    } else {
685 686
        ignore_value(VIR_STRDUP(ret, filename));
        return ret;
687
    }
688 689
}

C
Cole Robinson 已提交
690 691 692 693 694 695
static xmlNodePtr
testParseXMLDocFromFile(xmlNodePtr node, const char *file, const char *type)
{
    xmlNodePtr ret = NULL;
    xmlDocPtr doc = NULL;
    char *absFile = NULL;
696
    VIR_AUTOFREE(char *) relFile = NULL;
C
Cole Robinson 已提交
697

698
    if ((relFile = virXMLPropString(node, "file"))) {
C
Cole Robinson 已提交
699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
        absFile = testBuildFilename(file, 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;
    }

720
 error:
C
Cole Robinson 已提交
721 722 723 724
    xmlFreeDoc(doc);
    return ret;
}

725 726 727 728 729
static int
testParseNodeInfo(virNodeInfoPtr nodeInfo, xmlXPathContextPtr ctxt)
{
    long l;
    int ret;
730
    VIR_AUTOFREE(char *) str = NULL;
731

732
    ret = virXPathLong("string(/node/cpu/nodes[1])", ctxt, &l);
733 734 735
    if (ret == 0) {
        nodeInfo->nodes = l;
    } else if (ret == -2) {
736 737
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu nodes value"));
738
        goto error;
739
    }
740

741
    ret = virXPathLong("string(/node/cpu/sockets[1])", ctxt, &l);
742 743 744
    if (ret == 0) {
        nodeInfo->sockets = l;
    } else if (ret == -2) {
745 746
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu sockets value"));
747
        goto error;
748
    }
749

750
    ret = virXPathLong("string(/node/cpu/cores[1])", ctxt, &l);
751 752 753
    if (ret == 0) {
        nodeInfo->cores = l;
    } else if (ret == -2) {
754 755
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu cores value"));
756
        goto error;
757 758
    }

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

768 769
    nodeInfo->cpus = (nodeInfo->cores * nodeInfo->threads *
                      nodeInfo->sockets * nodeInfo->nodes);
770
    ret = virXPathLong("string(/node/cpu/active[1])", ctxt, &l);
771
    if (ret == 0) {
772
        if (l < nodeInfo->cpus)
773
            nodeInfo->cpus = l;
774
    } else if (ret == -2) {
775 776
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu active value"));
777
        goto error;
778
    }
779
    ret = virXPathLong("string(/node/cpu/mhz[1])", ctxt, &l);
780 781 782
    if (ret == 0) {
        nodeInfo->mhz = l;
    } else if (ret == -2) {
783 784
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu mhz value"));
785
        goto error;
786 787
    }

788
    str = virXPathString("string(/node/cpu/model[1])", ctxt);
789
    if (str != NULL) {
790
        if (virStrcpyStatic(nodeInfo->model, str) < 0) {
791 792
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Model %s too big for destination"), str);
C
Chris Lalancette 已提交
793 794
            goto error;
        }
795 796
    }

797
    ret = virXPathLong("string(/node/memory[1])", ctxt, &l);
798 799 800
    if (ret == 0) {
        nodeInfo->memory = l;
    } else if (ret == -2) {
801 802
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node memory value"));
803
        goto error;
804
    }
805

806
    return 0;
807
 error:
808 809 810
    return -1;
}

811
static int
812
testParseDomainSnapshots(testDriverPtr privconn,
813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 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
                         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;
863
 error:
864 865 866
    return ret;
}

867
static int
868
testParseDomains(testDriverPtr privconn,
C
Cole Robinson 已提交
869 870
                 const char *file,
                 xmlXPathContextPtr ctxt)
871 872 873
{
    int num, ret = -1;
    size_t i;
874
    virDomainObjPtr obj = NULL;
875
    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
876 877

    num = virXPathNodeSet("/node/domain", ctxt, &nodes);
878
    if (num < 0)
879
        return -1;
880

881
    for (i = 0; i < num; i++) {
882
        virDomainDefPtr def;
883
        testDomainNamespaceDefPtr nsdata;
C
Cole Robinson 已提交
884 885 886 887 888
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file, "domain");
        if (!node)
            goto error;

        def = virDomainDefParseNode(ctxt->doc, node,
889
                                    privconn->caps, privconn->xmlopt, NULL,
890
                                    VIR_DOMAIN_DEF_PARSE_INACTIVE);
C
Cole Robinson 已提交
891 892
        if (!def)
            goto error;
893

894
        if (testDomainGenerateIfnames(def) < 0 ||
895
            !(obj = virDomainObjListAdd(privconn->domains,
896
                                        def,
897
                                        privconn->xmlopt,
898
                                        0, NULL))) {
899
            virDomainDefFree(def);
900 901
            goto error;
        }
902

903
        if (testParseDomainSnapshots(privconn, obj, file, ctxt) < 0)
904 905
            goto error;

906
        nsdata = def->namespaceData;
907
        obj->persistent = !nsdata->transient;
C
Cole Robinson 已提交
908
        obj->hasManagedSave = nsdata->hasManagedSave;
909 910 911

        if (nsdata->runstate != VIR_DOMAIN_SHUTOFF) {
            if (testDomainStartState(privconn, obj,
912
                                     VIR_DOMAIN_RUNNING_BOOTED) < 0)
913 914 915
                goto error;
        } else {
            testDomainShutdownState(NULL, obj, 0);
916
        }
917
        virDomainObjSetState(obj, nsdata->runstate, 0);
918

919
        virDomainObjEndAPI(&obj);
920
    }
921

922
    ret = 0;
923
 error:
924
    virDomainObjEndAPI(&obj);
925 926 927
    return ret;
}

928

929
static int
930
testParseNetworks(testDriverPtr privconn,
C
Cole Robinson 已提交
931 932
                  const char *file,
                  xmlXPathContextPtr ctxt)
933
{
934
    int num;
935 936
    size_t i;
    virNetworkObjPtr obj;
937
    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
938 939

    num = virXPathNodeSet("/node/network", ctxt, &nodes);
940
    if (num < 0)
941
        return -1;
942 943

    for (i = 0; i < num; i++) {
944
        virNetworkDefPtr def;
C
Cole Robinson 已提交
945 946
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file, "network");
        if (!node)
947
            return -1;
948

C
Cole Robinson 已提交
949 950
        def = virNetworkDefParseNode(ctxt->doc, node);
        if (!def)
951
            return -1;
952

953
        if (!(obj = virNetworkObjAssignDef(privconn->networks, def, 0))) {
954
            virNetworkDefFree(def);
955
            return -1;
956
        }
957

958
        virNetworkObjSetActive(obj, true);
959
        virNetworkObjEndAPI(&obj);
960
    }
961

962
    return 0;
963 964
}

965

966
static int
967
testParseInterfaces(testDriverPtr privconn,
C
Cole Robinson 已提交
968 969
                    const char *file,
                    xmlXPathContextPtr ctxt)
970
{
971
    int num;
972 973
    size_t i;
    virInterfaceObjPtr obj;
974
    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
975 976

    num = virXPathNodeSet("/node/interface", ctxt, &nodes);
977
    if (num < 0)
978
        return -1;
979 980

    for (i = 0; i < num; i++) {
L
Laine Stump 已提交
981
        virInterfaceDefPtr def;
C
Cole Robinson 已提交
982 983 984
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "interface");
        if (!node)
985
            return -1;
L
Laine Stump 已提交
986

C
Cole Robinson 已提交
987 988
        def = virInterfaceDefParseNode(ctxt->doc, node);
        if (!def)
989
            return -1;
990

991
        if (!(obj = virInterfaceObjListAssignDef(privconn->ifaces, def))) {
L
Laine Stump 已提交
992
            virInterfaceDefFree(def);
993
            return -1;
L
Laine Stump 已提交
994
        }
995

996
        virInterfaceObjSetActive(obj, true);
997
        virInterfaceObjEndAPI(&obj);
998 999
    }

1000
    return 0;
1001 1002
}

1003

1004
static int
C
Cole Robinson 已提交
1005
testOpenVolumesForPool(const char *file,
1006
                       xmlXPathContextPtr ctxt,
1007 1008
                       virStoragePoolObjPtr obj,
                       int objidx)
1009
{
1010
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(obj);
1011
    size_t i;
1012 1013 1014
    int num;
    VIR_AUTOFREE(char *) vol_xpath = NULL;
    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
1015
    VIR_AUTOPTR(virStorageVolDef) volDef = NULL;
1016 1017

    /* Find storage volumes */
1018
    if (virAsprintf(&vol_xpath, "/node/pool[%d]/volume", objidx) < 0)
1019
        return -1;
1020 1021

    num = virXPathNodeSet(vol_xpath, ctxt, &nodes);
1022
    if (num < 0)
1023
        return -1;
1024 1025

    for (i = 0; i < num; i++) {
C
Cole Robinson 已提交
1026 1027 1028
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "volume");
        if (!node)
1029
            return -1;
1030

1031
        if (!(volDef = virStorageVolDefParseNode(def, ctxt->doc, node, 0)))
1032
            return -1;
1033

1034 1035
        if (!volDef->target.path) {
            if (virAsprintf(&volDef->target.path, "%s/%s",
1036
                            def->target.path, volDef->name) < 0)
1037
                return -1;
1038 1039
        }

1040
        if (!volDef->key && VIR_STRDUP(volDef->key, volDef->target.path) < 0)
1041
            return -1;
1042

1043
        if (virStoragePoolObjAddVol(obj, volDef) < 0)
1044
            return -1;
1045

1046 1047
        def->allocation += volDef->target.allocation;
        def->available = (def->capacity - def->allocation);
1048
        volDef = NULL;
L
Laine Stump 已提交
1049 1050
    }

1051
    return 0;
1052 1053
}

1054

1055
static int
1056
testParseStorage(testDriverPtr privconn,
C
Cole Robinson 已提交
1057 1058
                 const char *file,
                 xmlXPathContextPtr ctxt)
1059
{
1060
    int num;
1061 1062
    size_t i;
    virStoragePoolObjPtr obj;
1063
    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
1064 1065

    num = virXPathNodeSet("/node/pool", ctxt, &nodes);
1066
    if (num < 0)
1067
        return -1;
1068 1069

    for (i = 0; i < num; i++) {
C
Cole Robinson 已提交
1070
        virStoragePoolDefPtr def;
C
Cole Robinson 已提交
1071 1072 1073
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "pool");
        if (!node)
1074
            return -1;
C
Cole Robinson 已提交
1075

C
Cole Robinson 已提交
1076 1077
        def = virStoragePoolDefParseNode(ctxt->doc, node);
        if (!def)
1078
            return -1;
C
Cole Robinson 已提交
1079

1080
        if (!(obj = virStoragePoolObjAssignDef(privconn->pools, def, false))) {
C
Cole Robinson 已提交
1081
            virStoragePoolDefFree(def);
1082
            return -1;
C
Cole Robinson 已提交
1083 1084
        }

1085
        if (testStoragePoolObjSetDefaults(obj) == -1) {
1086
            virStoragePoolObjEndAPI(&obj);
1087
            return -1;
1088
        }
1089
        virStoragePoolObjSetActive(obj, true);
1090 1091

        /* Find storage volumes */
C
Cole Robinson 已提交
1092
        if (testOpenVolumesForPool(file, ctxt, obj, i+1) < 0) {
1093
            virStoragePoolObjEndAPI(&obj);
1094
            return -1;
1095 1096
        }

1097
        virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
1098 1099
    }

1100
    return 0;
1101 1102
}

1103

1104
static int
1105
testParseNodedevs(testDriverPtr privconn,
C
Cole Robinson 已提交
1106 1107
                  const char *file,
                  xmlXPathContextPtr ctxt)
1108
{
1109
    int num;
1110 1111
    size_t i;
    virNodeDeviceObjPtr obj;
1112
    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
1113 1114

    num = virXPathNodeSet("/node/device", ctxt, &nodes);
1115
    if (num < 0)
1116
        return -1;
1117 1118

    for (i = 0; i < num; i++) {
1119
        virNodeDeviceDefPtr def;
C
Cole Robinson 已提交
1120 1121 1122
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                  "nodedev");
        if (!node)
1123
            return -1;
1124

C
Cole Robinson 已提交
1125 1126
        def = virNodeDeviceDefParseNode(ctxt->doc, node, 0, NULL);
        if (!def)
1127
            return -1;
1128

1129
        if (!(obj = virNodeDeviceObjListAssignDef(privconn->devs, def))) {
1130
            virNodeDeviceDefFree(def);
1131
            return -1;
1132
        }
1133

1134
        virNodeDeviceObjSetSkipUpdateCaps(obj, true);
1135
        virNodeDeviceObjEndAPI(&obj);
1136 1137
    }

1138
    return 0;
1139 1140
}

1141
static int
1142
testParseAuthUsers(testDriverPtr privconn,
1143 1144
                   xmlXPathContextPtr ctxt)
{
1145
    int num;
1146
    size_t i;
1147
    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
1148 1149 1150

    num = virXPathNodeSet("/node/auth/user", ctxt, &nodes);
    if (num < 0)
1151
        return -1;
1152 1153 1154

    privconn->numAuths = num;
    if (num && VIR_ALLOC_N(privconn->auths, num) < 0)
1155
        return -1;
1156 1157

    for (i = 0; i < num; i++) {
1158
        VIR_AUTOFREE(char *) username = NULL;
1159 1160 1161 1162 1163 1164

        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"));
1165
            return -1;
1166 1167
        }
        /* This field is optional. */
1168 1169
        privconn->auths[i].password = virXMLPropString(nodes[i], "password");
        VIR_STEAL_PTR(privconn->auths[i].username, username);
1170 1171
    }

1172
    return 0;
1173
}
1174

C
Cole Robinson 已提交
1175 1176 1177 1178 1179
static int
testOpenParse(testDriverPtr privconn,
              const char *file,
              xmlXPathContextPtr ctxt)
{
1180
    if (!virXMLNodeNameEqual(ctxt->node, "node")) {
C
Cole Robinson 已提交
1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205
        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;
}

1206 1207
/* No shared state between simultaneous test connections initialized
 * from a file.  */
1208 1209 1210 1211 1212
static int
testOpenFromFile(virConnectPtr conn, const char *file)
{
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
1213
    testDriverPtr privconn;
1214

1215
    if (!(privconn = testDriverNew()))
1216
        return VIR_DRV_OPEN_ERROR;
1217

1218
    virObjectLock(privconn);
1219 1220 1221 1222 1223
    conn->privateData = privconn;

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

1224
    if (!(doc = virXMLParseFileCtxt(file, &ctxt)))
1225 1226 1227 1228 1229
        goto error;

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

C
Cole Robinson 已提交
1230
    if (testOpenParse(privconn, file, ctxt) < 0)
1231
        goto error;
1232

J
Jim Meyering 已提交
1233
    xmlXPathFreeContext(ctxt);
1234
    xmlFreeDoc(doc);
1235
    virObjectUnlock(privconn);
1236

1237
    return VIR_DRV_OPEN_SUCCESS;
1238 1239

 error:
J
Jim Meyering 已提交
1240
    xmlXPathFreeContext(ctxt);
1241
    xmlFreeDoc(doc);
1242
    virObjectUnref(privconn);
1243
    conn->privateData = NULL;
1244
    return VIR_DRV_OPEN_ERROR;
1245 1246
}

1247 1248 1249 1250 1251 1252
/* 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)
{
1253
    int ret = VIR_DRV_OPEN_ERROR;
1254
    testDriverPtr privconn = NULL;
1255 1256
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
1257
    size_t i;
1258 1259

    virMutexLock(&defaultLock);
1260 1261
    if (defaultPrivconn) {
        conn->privateData = virObjectRef(defaultPrivconn);
1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274
        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;
1275 1276 1277 1278
    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;
1279
    }
1280
    for (i = 0; i < 16; i++) {
1281 1282 1283
        virBitmapPtr siblings = virBitmapNew(16);
        if (!siblings)
            goto error;
1284 1285 1286 1287 1288
        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;
1289 1290 1291 1292 1293
    }

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

1294 1295
    if (!(doc = virXMLParseStringCtxt(defaultConnXML,
                                      _("(test driver)"), &ctxt)))
1296 1297
        goto error;

1298
    if (testOpenParse(privconn, NULL, ctxt) < 0)
1299 1300
        goto error;

1301
    defaultPrivconn = privconn;
1302 1303 1304
    ret = VIR_DRV_OPEN_SUCCESS;
 cleanup:
    virMutexUnlock(&defaultLock);
1305 1306
    xmlXPathFreeContext(ctxt);
    xmlFreeDoc(doc);
1307
    return ret;
1308 1309

 error:
1310
    virObjectUnref(privconn);
1311
    conn->privateData = NULL;
1312
    goto cleanup;
1313 1314
}

1315 1316 1317 1318
static int
testConnectAuthenticate(virConnectPtr conn,
                        virConnectAuthPtr auth)
{
1319
    testDriverPtr privconn = conn->privateData;
1320 1321
    int ret = -1;
    ssize_t i;
1322 1323
    VIR_AUTOFREE(char *) username = NULL;
    VIR_AUTOFREE(char *) password = NULL;
1324

1325
    virObjectLock(privconn);
1326
    if (privconn->numAuths == 0) {
1327
        virObjectUnlock(privconn);
1328
        return 0;
1329
    }
1330 1331 1332 1333

    /* Authentication is required because the test XML contains a
     * non-empty <auth/> section.  First we must ask for a username.
     */
1334 1335
    if (!(username = virAuthGetUsername(conn, auth, "test", NULL,
                                        "localhost"/*?*/)))
1336 1337 1338 1339 1340 1341 1342 1343 1344
        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;

1345
 found_user:
1346 1347
    /* Even if we didn't find the user, we still ask for a password. */
    if (i == -1 || privconn->auths[i].password != NULL) {
1348 1349
        if (!(password = virAuthGetPassword(conn, auth, "test", username,
                                            "localhost")))
1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360
            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;
1361
 cleanup:
1362
    virObjectUnlock(privconn);
1363 1364
    return ret;
}
1365

1366 1367 1368 1369

static void
testDriverCloseInternal(testDriverPtr driver)
{
1370 1371 1372
    virMutexLock(&defaultLock);
    bool disposed = !virObjectUnref(driver);
    if (disposed && driver == defaultPrivconn)
1373
        defaultPrivconn = NULL;
1374
    virMutexUnlock(&defaultLock);
1375 1376 1377 1378 1379 1380 1381 1382
}


static virDrvOpenStatus
testConnectOpen(virConnectPtr conn,
                virConnectAuthPtr auth,
                virConfPtr conf ATTRIBUTE_UNUSED,
                unsigned int flags)
1383
{
1384
    int ret;
1385

E
Eric Blake 已提交
1386 1387
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

1388 1389
    if (conn->uri->path[0] == '\0' ||
        (conn->uri->path[0] == '/' && conn->uri->path[1] == '\0')) {
1390 1391
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("testOpen: supply a path or use test:///default"));
1392 1393
        return VIR_DRV_OPEN_ERROR;
    }
1394

1395
    if (STREQ(conn->uri->path, "/default"))
1396 1397
        ret = testOpenDefault(conn);
    else
1398
        ret = testOpenFromFile(conn,
1399
                               conn->uri->path);
1400

1401 1402 1403
    if (ret != VIR_DRV_OPEN_SUCCESS)
        return ret;

1404
    /* Fake authentication. */
1405 1406 1407
    if (testConnectAuthenticate(conn, auth) < 0) {
        testDriverCloseInternal(conn->privateData);
        conn->privateData = NULL;
1408
        return VIR_DRV_OPEN_ERROR;
1409
    }
1410

1411
    return VIR_DRV_OPEN_SUCCESS;
1412 1413
}

1414

1415 1416 1417 1418
static int
testConnectClose(virConnectPtr conn)
{
    testDriverCloseInternal(conn->privateData);
1419
    conn->privateData = NULL;
1420
    return 0;
1421 1422
}

1423

1424 1425
static int testConnectGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
                                 unsigned long *hvVer)
1426
{
1427
    *hvVer = 2;
1428
    return 0;
1429 1430
}

1431 1432 1433 1434 1435 1436
static char *testConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return virGetHostname();
}


1437
static int testConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
1438 1439 1440 1441
{
    return 1;
}

1442
static int testConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
1443 1444 1445 1446
{
    return 0;
}

1447
static int testConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
1448 1449 1450 1451
{
    return 1;
}

1452 1453
static int testConnectGetMaxVcpus(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type ATTRIBUTE_UNUSED)
1454 1455 1456 1457
{
    return 32;
}

1458 1459 1460 1461 1462 1463
static char *
testConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED,
                       const char **xmlCPUs,
                       unsigned int ncpus,
                       unsigned int flags)
{
J
Jiri Denemark 已提交
1464 1465 1466
    virCPUDefPtr *cpus = NULL;
    virCPUDefPtr cpu = NULL;
    char *cpustr = NULL;
1467 1468 1469

    virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, NULL);

J
Jiri Denemark 已提交
1470 1471 1472
    if (!(cpus = virCPUDefListParse(xmlCPUs, ncpus, VIR_CPU_TYPE_HOST)))
        goto cleanup;

1473
    if (!(cpu = virCPUBaseline(VIR_ARCH_NONE, cpus, ncpus, NULL, NULL, false)))
J
Jiri Denemark 已提交
1474 1475 1476 1477 1478 1479
        goto cleanup;

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

1480
    cpustr = virCPUDefFormat(cpu, NULL);
J
Jiri Denemark 已提交
1481 1482 1483 1484

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

J
Jiri Denemark 已提交
1486
    return cpustr;
1487 1488
}

1489 1490
static int testNodeGetInfo(virConnectPtr conn,
                           virNodeInfoPtr info)
1491
{
1492
    testDriverPtr privconn = conn->privateData;
1493
    virObjectLock(privconn);
1494
    memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo));
1495
    virObjectUnlock(privconn);
1496
    return 0;
1497 1498
}

1499
static char *testConnectGetCapabilities(virConnectPtr conn)
1500
{
1501
    testDriverPtr privconn = conn->privateData;
1502
    char *xml;
1503
    virObjectLock(privconn);
1504
    xml = virCapabilitiesFormatXML(privconn->caps);
1505
    virObjectUnlock(privconn);
1506
    return xml;
1507 1508
}

1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528
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;
}

1529 1530 1531 1532 1533 1534
static const char *
testConnectGetType(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return "TEST";
}

1535
static int testConnectNumOfDomains(virConnectPtr conn)
1536
{
1537
    testDriverPtr privconn = conn->privateData;
1538
    int count;
1539

1540
    virObjectLock(privconn);
1541
    count = virDomainObjListNumOfDomains(privconn->domains, true, NULL, NULL);
1542
    virObjectUnlock(privconn);
1543

1544
    return count;
1545 1546
}

1547 1548 1549
static int testDomainIsActive(virDomainPtr dom)
{
    virDomainObjPtr obj;
1550
    int ret;
1551

1552 1553
    if (!(obj = testDomObjFromDomain(dom)))
        return -1;
1554

1555 1556
    ret = virDomainObjIsActive(obj);
    virDomainObjEndAPI(&obj);
1557 1558 1559 1560 1561 1562
    return ret;
}

static int testDomainIsPersistent(virDomainPtr dom)
{
    virDomainObjPtr obj;
1563 1564 1565 1566
    int ret;

    if (!(obj = testDomObjFromDomain(dom)))
        return -1;
1567 1568 1569

    ret = obj->persistent;

1570
    virDomainObjEndAPI(&obj);
1571 1572 1573
    return ret;
}

1574 1575 1576 1577 1578
static int testDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
{
    return 0;
}

1579
static virDomainPtr
1580
testDomainCreateXML(virConnectPtr conn, const char *xml,
1581
                      unsigned int flags)
1582
{
1583
    testDriverPtr privconn = conn->privateData;
1584
    virDomainPtr ret = NULL;
1585
    virDomainDefPtr def;
1586
    virDomainObjPtr dom = NULL;
1587
    virObjectEventPtr event = NULL;
1588
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
1589

1590 1591 1592
    virCheckFlags(VIR_DOMAIN_START_VALIDATE, NULL);

    if (flags & VIR_DOMAIN_START_VALIDATE)
1593
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
1594

1595
    virObjectLock(privconn);
1596
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
1597
                                       NULL, parse_flags)) == NULL)
1598
        goto cleanup;
1599

1600
    if (testDomainGenerateIfnames(def) < 0)
1601
        goto cleanup;
1602
    if (!(dom = virDomainObjListAdd(privconn->domains,
1603
                                    def,
1604
                                    privconn->xmlopt,
1605
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
1606 1607
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
1608 1609
        goto cleanup;
    def = NULL;
1610

1611
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_BOOTED) < 0) {
1612
        if (!dom->persistent)
1613
            virDomainObjListRemove(privconn->domains, dom);
1614
        goto cleanup;
1615
    }
1616

1617
    event = virDomainEventLifecycleNewFromObj(dom,
1618 1619 1620
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);

1621
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
1622

1623
 cleanup:
1624
    virDomainObjEndAPI(&dom);
1625
    virObjectEventStateQueue(privconn->eventState, event);
1626
    virDomainDefFree(def);
1627
    virObjectUnlock(privconn);
1628
    return ret;
1629 1630 1631
}


1632
static virDomainPtr testDomainLookupByID(virConnectPtr conn,
1633
                                         int id)
1634
{
1635
    testDriverPtr privconn = conn->privateData;
1636 1637
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1638

1639
    if (!(dom = virDomainObjListFindByID(privconn->domains, id))) {
1640
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1641
        return NULL;
1642 1643
    }

1644
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
1645

1646
    virDomainObjEndAPI(&dom);
1647
    return ret;
1648 1649
}

1650
static virDomainPtr testDomainLookupByUUID(virConnectPtr conn,
1651
                                           const unsigned char *uuid)
1652
{
1653
    testDriverPtr privconn = conn->privateData;
1654
    virDomainPtr ret = NULL;
1655
    virDomainObjPtr dom;
1656

1657
    if (!(dom = virDomainObjListFindByUUID(privconn->domains, uuid))) {
1658
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1659
        return NULL;
1660
    }
1661

1662
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
1663

1664
    virDomainObjEndAPI(&dom);
1665
    return ret;
1666 1667
}

1668
static virDomainPtr testDomainLookupByName(virConnectPtr conn,
1669
                                           const char *name)
1670
{
1671
    testDriverPtr privconn = conn->privateData;
1672 1673
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1674

1675
    if (!(dom = virDomainObjListFindByName(privconn->domains, name))) {
1676
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1677
        goto cleanup;
1678
    }
1679

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

1682
 cleanup:
1683
    virDomainObjEndAPI(&dom);
1684
    return ret;
1685 1686
}

1687 1688 1689
static int testConnectListDomains(virConnectPtr conn,
                                  int *ids,
                                  int maxids)
1690
{
1691
    testDriverPtr privconn = conn->privateData;
1692

1693 1694
    return virDomainObjListGetActiveIDs(privconn->domains, ids, maxids,
                                        NULL, NULL);
1695 1696
}

1697 1698
static int testDomainDestroyFlags(virDomainPtr domain,
                                  unsigned int flags)
1699
{
1700
    testDriverPtr privconn = domain->conn->privateData;
1701
    virDomainObjPtr privdom;
1702
    virObjectEventPtr event = NULL;
1703
    int ret = -1;
1704

1705 1706
    virCheckFlags(VIR_DOMAIN_DESTROY_GRACEFUL, -1);

1707
    if (!(privdom = testDomObjFromDomain(domain)))
1708
        goto cleanup;
1709

1710
    if (virDomainObjCheckActive(privdom) < 0)
1711 1712
        goto cleanup;

J
Jiri Denemark 已提交
1713
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_DESTROYED);
1714
    event = virDomainEventLifecycleNewFromObj(privdom,
1715 1716
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
1717

1718
    if (!privdom->persistent)
1719
        virDomainObjListRemove(privconn->domains, privdom);
1720 1721

    ret = 0;
1722
 cleanup:
1723
    virDomainObjEndAPI(&privdom);
1724
    virObjectEventStateQueue(privconn->eventState, event);
1725
    return ret;
1726 1727
}

1728 1729 1730 1731 1732
static int testDomainDestroy(virDomainPtr domain)
{
    return testDomainDestroyFlags(domain, 0);
}

1733
static int testDomainResume(virDomainPtr domain)
1734
{
1735
    testDriverPtr privconn = domain->conn->privateData;
1736
    virDomainObjPtr privdom;
1737
    virObjectEventPtr event = NULL;
1738
    int ret = -1;
1739

1740 1741
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1742

J
Jiri Denemark 已提交
1743
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_PAUSED) {
1744 1745
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"),
                       domain->name);
1746
        goto cleanup;
1747
    }
1748

J
Jiri Denemark 已提交
1749 1750
    virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                         VIR_DOMAIN_RUNNING_UNPAUSED);
1751
    event = virDomainEventLifecycleNewFromObj(privdom,
1752 1753
                                     VIR_DOMAIN_EVENT_RESUMED,
                                     VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
1754 1755
    ret = 0;

1756
 cleanup:
1757
    virDomainObjEndAPI(&privdom);
1758
    virObjectEventStateQueue(privconn->eventState, event);
1759
    return ret;
1760 1761
}

1762
static int testDomainSuspend(virDomainPtr domain)
1763
{
1764
    testDriverPtr privconn = domain->conn->privateData;
1765
    virDomainObjPtr privdom;
1766
    virObjectEventPtr event = NULL;
1767
    int ret = -1;
J
Jiri Denemark 已提交
1768
    int state;
1769

1770 1771
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1772

J
Jiri Denemark 已提交
1773 1774
    state = virDomainObjGetState(privdom, NULL);
    if (state == VIR_DOMAIN_SHUTOFF || state == VIR_DOMAIN_PAUSED) {
1775 1776
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"),
                       domain->name);
1777
        goto cleanup;
1778
    }
1779

J
Jiri Denemark 已提交
1780
    virDomainObjSetState(privdom, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
1781
    event = virDomainEventLifecycleNewFromObj(privdom,
1782 1783
                                     VIR_DOMAIN_EVENT_SUSPENDED,
                                     VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
1784 1785
    ret = 0;

1786
 cleanup:
1787
    virDomainObjEndAPI(&privdom);
1788
    virObjectEventStateQueue(privconn->eventState, event);
1789
    return ret;
1790 1791
}

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

1800 1801
    virCheckFlags(0, -1);

1802

1803
    if (!(privdom = testDomObjFromDomain(domain)))
1804
        goto cleanup;
1805

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

J
Jiri Denemark 已提交
1812
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1813
    event = virDomainEventLifecycleNewFromObj(privdom,
1814 1815
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1816

1817
    if (!privdom->persistent)
1818
        virDomainObjListRemove(privconn->domains, privdom);
1819

1820
    ret = 0;
1821
 cleanup:
1822
    virDomainObjEndAPI(&privdom);
1823
    virObjectEventStateQueue(privconn->eventState, event);
1824
    return ret;
1825 1826
}

1827
static int testDomainShutdown(virDomainPtr domain)
1828
{
1829
    return testDomainShutdownFlags(domain, 0);
1830 1831
}

1832
/* Similar behaviour as shutdown */
1833
static int testDomainReboot(virDomainPtr domain,
1834
                            unsigned int action ATTRIBUTE_UNUSED)
1835
{
1836
    testDriverPtr privconn = domain->conn->privateData;
1837
    virDomainObjPtr privdom;
1838
    virObjectEventPtr event = NULL;
1839
    int ret = -1;
1840 1841


1842
    if (!(privdom = testDomObjFromDomain(domain)))
1843
        goto cleanup;
1844

1845
    if (virDomainObjCheckActive(privdom) < 0)
1846 1847
        goto cleanup;

J
Jiri Denemark 已提交
1848 1849 1850
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTDOWN,
                         VIR_DOMAIN_SHUTDOWN_USER);

1851
    switch (privdom->def->onReboot) {
1852
    case VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY:
J
Jiri Denemark 已提交
1853 1854
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1855 1856
        break;

1857
    case VIR_DOMAIN_LIFECYCLE_ACTION_RESTART:
J
Jiri Denemark 已提交
1858 1859
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
1860 1861
        break;

1862
    case VIR_DOMAIN_LIFECYCLE_ACTION_PRESERVE:
J
Jiri Denemark 已提交
1863 1864
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1865 1866
        break;

1867
    case VIR_DOMAIN_LIFECYCLE_ACTION_RESTART_RENAME:
J
Jiri Denemark 已提交
1868 1869
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
1870
        break;
1871

1872
    default:
J
Jiri Denemark 已提交
1873 1874
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1875 1876
        break;
    }
1877

J
Jiri Denemark 已提交
1878 1879
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1880
        event = virDomainEventLifecycleNewFromObj(privdom,
1881 1882
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1883

1884
        if (!privdom->persistent)
1885
            virDomainObjListRemove(privconn->domains, privdom);
1886 1887
    }

1888
    ret = 0;
1889
 cleanup:
1890
    virDomainObjEndAPI(&privdom);
1891
    virObjectEventStateQueue(privconn->eventState, event);
1892
    return ret;
1893 1894
}

1895
static int testDomainGetInfo(virDomainPtr domain,
1896
                             virDomainInfoPtr info)
1897
{
1898
    struct timeval tv;
1899
    virDomainObjPtr privdom;
1900
    int ret = -1;
1901

1902 1903
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1904 1905

    if (gettimeofday(&tv, NULL) < 0) {
1906 1907
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("getting time of day"));
1908
        goto cleanup;
1909 1910
    }

J
Jiri Denemark 已提交
1911
    info->state = virDomainObjGetState(privdom, NULL);
1912
    info->memory = privdom->def->mem.cur_balloon;
1913
    info->maxMem = virDomainDefGetMemoryTotal(privdom->def);
1914
    info->nrVirtCpu = virDomainDefGetVcpus(privdom->def);
1915
    info->cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
1916 1917
    ret = 0;

1918
 cleanup:
1919
    virDomainObjEndAPI(&privdom);
1920
    return ret;
1921 1922
}

1923 1924 1925 1926 1927 1928 1929 1930 1931 1932
static int
testDomainGetState(virDomainPtr domain,
                   int *state,
                   int *reason,
                   unsigned int flags)
{
    virDomainObjPtr privdom;

    virCheckFlags(0, -1);

1933 1934
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1935

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

1938
    virDomainObjEndAPI(&privdom);
1939 1940

    return 0;
1941 1942
}

1943 1944
#define TEST_SAVE_MAGIC "TestGuestMagic"

1945 1946 1947
static int
testDomainSaveFlags(virDomainPtr domain, const char *path,
                    const char *dxml, unsigned int flags)
1948
{
1949
    testDriverPtr privconn = domain->conn->privateData;
1950 1951
    int fd = -1;
    int len;
1952
    virDomainObjPtr privdom;
1953
    virObjectEventPtr event = NULL;
1954
    int ret = -1;
1955
    VIR_AUTOFREE(char *) xml = NULL;
1956

1957 1958
    virCheckFlags(0, -1);
    if (dxml) {
1959 1960
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1961 1962 1963
        return -1;
    }

1964

1965
    if (!(privdom = testDomObjFromDomain(domain)))
1966
        goto cleanup;
1967

1968
    if (virDomainObjCheckActive(privdom) < 0)
1969 1970
        goto cleanup;

1971
    xml = virDomainDefFormat(privdom->def, privconn->caps,
1972
                             VIR_DOMAIN_DEF_FORMAT_SECURE);
C
Cole Robinson 已提交
1973

1974
    if (xml == NULL) {
1975
        virReportSystemError(errno,
1976 1977
                             _("saving domain '%s' failed to allocate space for metadata"),
                             domain->name);
1978
        goto cleanup;
1979
    }
1980 1981

    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
1982
        virReportSystemError(errno,
1983 1984
                             _("saving domain '%s' to '%s': open failed"),
                             domain->name, path);
1985
        goto cleanup;
1986
    }
1987
    len = strlen(xml);
1988
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
1989
        virReportSystemError(errno,
1990 1991
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1992
        goto cleanup;
1993
    }
1994
    if (safewrite(fd, (char*)&len, sizeof(len)) < 0) {
1995
        virReportSystemError(errno,
1996 1997
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1998
        goto cleanup;
1999
    }
2000
    if (safewrite(fd, xml, len) < 0) {
2001
        virReportSystemError(errno,
2002 2003
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
2004
        goto cleanup;
2005
    }
2006

2007
    if (VIR_CLOSE(fd) < 0) {
2008
        virReportSystemError(errno,
2009 2010
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
2011
        goto cleanup;
2012
    }
2013 2014
    fd = -1;

J
Jiri Denemark 已提交
2015
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SAVED);
2016
    event = virDomainEventLifecycleNewFromObj(privdom,
2017 2018
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
2019

2020
    if (!privdom->persistent)
2021
        virDomainObjListRemove(privconn->domains, privdom);
2022

2023
    ret = 0;
2024
 cleanup:
2025 2026
    /* Don't report failure in close or unlink, because
     * in either case we're already in a failure scenario
Y
Yuri Chornoivan 已提交
2027
     * and have reported an earlier error */
2028
    if (ret != 0) {
2029
        VIR_FORCE_CLOSE(fd);
2030 2031
        unlink(path);
    }
2032
    virDomainObjEndAPI(&privdom);
2033
    virObjectEventStateQueue(privconn->eventState, event);
2034
    return ret;
2035 2036
}

2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048
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)
2049
{
2050
    testDriverPtr privconn = conn->privateData;
2051
    char magic[15];
2052 2053 2054
    int fd = -1;
    int len;
    virDomainDefPtr def = NULL;
2055
    virDomainObjPtr dom = NULL;
2056
    virObjectEventPtr event = NULL;
2057
    int ret = -1;
2058
    VIR_AUTOFREE(char *) xml = NULL;
2059

2060 2061
    virCheckFlags(0, -1);
    if (dxml) {
2062 2063
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
2064 2065 2066
        return -1;
    }

2067
    if ((fd = open(path, O_RDONLY)) < 0) {
2068
        virReportSystemError(errno,
2069 2070
                             _("cannot read domain image '%s'"),
                             path);
2071
        goto cleanup;
2072
    }
2073
    if (saferead(fd, magic, sizeof(magic)) != sizeof(magic)) {
2074
        virReportSystemError(errno,
2075 2076
                             _("incomplete save header in '%s'"),
                             path);
2077
        goto cleanup;
2078
    }
2079
    if (memcmp(magic, TEST_SAVE_MAGIC, sizeof(magic))) {
2080 2081
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("mismatched header magic"));
2082
        goto cleanup;
2083
    }
2084
    if (saferead(fd, (char*)&len, sizeof(len)) != sizeof(len)) {
2085
        virReportSystemError(errno,
2086 2087
                             _("failed to read metadata length in '%s'"),
                             path);
2088
        goto cleanup;
2089 2090
    }
    if (len < 1 || len > 8192) {
2091 2092
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("length of metadata out of range"));
2093
        goto cleanup;
2094
    }
2095
    if (VIR_ALLOC_N(xml, len+1) < 0)
2096
        goto cleanup;
2097
    if (saferead(fd, xml, len) != len) {
2098
        virReportSystemError(errno,
2099
                             _("incomplete metadata in '%s'"), path);
2100
        goto cleanup;
2101 2102
    }
    xml[len] = '\0';
2103

2104
    def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
2105
                                  NULL, VIR_DOMAIN_DEF_PARSE_INACTIVE);
2106
    if (!def)
2107
        goto cleanup;
2108

2109
    if (testDomainGenerateIfnames(def) < 0)
2110
        goto cleanup;
2111
    if (!(dom = virDomainObjListAdd(privconn->domains,
2112
                                    def,
2113
                                    privconn->xmlopt,
2114 2115 2116
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
2117 2118
        goto cleanup;
    def = NULL;
2119

2120
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_RESTORED) < 0) {
2121
        if (!dom->persistent)
2122
            virDomainObjListRemove(privconn->domains, dom);
2123
        goto cleanup;
2124
    }
2125

2126
    event = virDomainEventLifecycleNewFromObj(dom,
2127 2128
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
2129
    ret = 0;
2130

2131
 cleanup:
2132
    virDomainDefFree(def);
2133
    VIR_FORCE_CLOSE(fd);
2134
    virDomainObjEndAPI(&dom);
2135
    virObjectEventStateQueue(privconn->eventState, event);
2136
    return ret;
2137 2138
}

2139 2140 2141 2142 2143 2144 2145
static int
testDomainRestore(virConnectPtr conn,
                  const char *path)
{
    return testDomainRestoreFlags(conn, path, NULL, 0);
}

2146 2147 2148 2149
static int testDomainCoreDumpWithFormat(virDomainPtr domain,
                                        const char *to,
                                        unsigned int dumpformat,
                                        unsigned int flags)
2150
{
2151
    testDriverPtr privconn = domain->conn->privateData;
2152
    int fd = -1;
2153
    virDomainObjPtr privdom;
2154
    virObjectEventPtr event = NULL;
2155
    int ret = -1;
2156

E
Eric Blake 已提交
2157 2158
    virCheckFlags(VIR_DUMP_CRASH, -1);

2159

2160
    if (!(privdom = testDomObjFromDomain(domain)))
2161
        goto cleanup;
2162

2163
    if (virDomainObjCheckActive(privdom) < 0)
2164 2165
        goto cleanup;

2166
    if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
2167
        virReportSystemError(errno,
2168 2169
                             _("domain '%s' coredump: failed to open %s"),
                             domain->name, to);
2170
        goto cleanup;
2171
    }
2172
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
2173
        virReportSystemError(errno,
2174 2175
                             _("domain '%s' coredump: failed to write header to %s"),
                             domain->name, to);
2176
        goto cleanup;
2177
    }
2178
    if (VIR_CLOSE(fd) < 0) {
2179
        virReportSystemError(errno,
2180 2181
                             _("domain '%s' coredump: write failed: %s"),
                             domain->name, to);
2182
        goto cleanup;
2183
    }
2184

2185 2186 2187 2188 2189 2190 2191
    /* 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;
    }

2192
    if (flags & VIR_DUMP_CRASH) {
J
Jiri Denemark 已提交
2193
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_CRASHED);
2194
        event = virDomainEventLifecycleNewFromObj(privdom,
2195 2196
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
2197
        if (!privdom->persistent)
2198
            virDomainObjListRemove(privconn->domains, privdom);
2199
    }
2200

2201
    ret = 0;
2202
 cleanup:
2203
    VIR_FORCE_CLOSE(fd);
2204
    virDomainObjEndAPI(&privdom);
2205
    virObjectEventStateQueue(privconn->eventState, event);
2206
    return ret;
2207 2208
}

2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222

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)
{
2223 2224 2225
    char *ret;

    ignore_value(VIR_STRDUP(ret, "linux"));
2226
    return ret;
2227 2228
}

2229 2230 2231

static unsigned long long
testDomainGetMaxMemory(virDomainPtr domain)
2232
{
2233
    virDomainObjPtr privdom;
2234
    unsigned long long ret = 0;
2235

2236 2237
    if (!(privdom = testDomObjFromDomain(domain)))
        return 0;
2238

2239
    ret = virDomainDefGetMemoryTotal(privdom->def);
2240

2241
    virDomainObjEndAPI(&privdom);
2242
    return ret;
2243 2244
}

2245 2246
static int testDomainSetMaxMemory(virDomainPtr domain,
                                  unsigned long memory)
2247
{
2248 2249
    virDomainObjPtr privdom;

2250 2251
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2252 2253

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

2256
    virDomainObjEndAPI(&privdom);
2257
    return 0;
2258 2259
}

2260 2261
static int testDomainSetMemory(virDomainPtr domain,
                               unsigned long memory)
2262
{
2263
    virDomainObjPtr privdom;
2264
    int ret = -1;
2265

2266 2267
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2268

2269
    if (memory > virDomainDefGetMemoryTotal(privdom->def)) {
2270
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2271
        goto cleanup;
2272
    }
2273

2274
    privdom->def->mem.cur_balloon = memory;
2275 2276
    ret = 0;

2277
 cleanup:
2278
    virDomainObjEndAPI(&privdom);
2279
    return ret;
2280 2281
}

2282 2283
static int
testDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
C
Cole Robinson 已提交
2284
{
2285 2286 2287 2288
    virDomainObjPtr vm;
    virDomainDefPtr def;
    int ret = -1;

2289 2290
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2291 2292
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

2293 2294
    if (!(vm = testDomObjFromDomain(domain)))
        return -1;
2295

2296
    if (!(def = virDomainObjGetOneDef(vm, flags)))
2297
        goto cleanup;
2298

2299 2300 2301
    if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
        ret = virDomainDefGetVcpusMax(def);
    else
2302
        ret = virDomainDefGetVcpus(def);
2303

2304
 cleanup:
2305
    virDomainObjEndAPI(&vm);
2306
    return ret;
C
Cole Robinson 已提交
2307 2308
}

2309 2310 2311
static int
testDomainGetMaxVcpus(virDomainPtr domain)
{
2312
    return testDomainGetVcpusFlags(domain, (VIR_DOMAIN_AFFECT_LIVE |
2313 2314 2315 2316 2317 2318 2319
                                            VIR_DOMAIN_VCPU_MAXIMUM));
}

static int
testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
                        unsigned int flags)
{
2320
    testDriverPtr driver = domain->conn->privateData;
2321
    virDomainObjPtr privdom = NULL;
2322
    virDomainDefPtr def;
2323
    virDomainDefPtr persistentDef;
C
Cole Robinson 已提交
2324 2325
    int ret = -1, maxvcpus;

2326 2327
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2328 2329
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

2330
    if ((maxvcpus = testConnectGetMaxVcpus(domain->conn, NULL)) < 0)
2331
        return -1;
2332 2333

    if (nrCpus > maxvcpus) {
2334
        virReportError(VIR_ERR_INVALID_ARG,
2335 2336
                       _("requested cpu amount exceeds maximum supported amount "
                         "(%d > %d)"), nrCpus, maxvcpus);
2337 2338
        return -1;
    }
2339

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

2343
    if (virDomainObjGetDefs(privdom, flags, &def, &persistentDef) < 0)
C
Cole Robinson 已提交
2344 2345
        goto cleanup;

2346
    if (def && virDomainDefGetVcpusMax(def) < nrCpus) {
2347 2348
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested cpu amount exceeds maximum (%d > %d)"),
2349
                       nrCpus, virDomainDefGetVcpusMax(def));
2350
        goto cleanup;
2351
    }
2352

2353 2354
    if (persistentDef &&
        !(flags & VIR_DOMAIN_VCPU_MAXIMUM) &&
2355
        virDomainDefGetVcpusMax(persistentDef) < nrCpus) {
2356 2357
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested cpu amount exceeds maximum (%d > %d)"),
2358
                       nrCpus, virDomainDefGetVcpusMax(persistentDef));
2359
        goto cleanup;
2360
    }
2361

2362 2363 2364
    if (def &&
        virDomainDefSetVcpus(def, nrCpus) < 0)
        goto cleanup;
2365

2366 2367
    if (persistentDef) {
        if (flags & VIR_DOMAIN_VCPU_MAXIMUM) {
2368 2369
            if (virDomainDefSetVcpusMax(persistentDef, nrCpus,
                                        driver->xmlopt) < 0)
2370
                goto cleanup;
2371
        } else {
2372 2373
            if (virDomainDefSetVcpus(persistentDef, nrCpus) < 0)
                goto cleanup;
2374
        }
2375
    }
2376

2377 2378
    ret = 0;

2379
 cleanup:
2380
    virDomainObjEndAPI(&privdom);
2381
    return ret;
2382 2383
}

2384
static int
2385
testDomainSetVcpus(virDomainPtr domain, unsigned int nrCpus)
2386
{
2387
    return testDomainSetVcpusFlags(domain, nrCpus, VIR_DOMAIN_AFFECT_LIVE);
2388 2389
}

C
Cole Robinson 已提交
2390 2391 2392 2393 2394 2395
static int testDomainGetVcpus(virDomainPtr domain,
                              virVcpuInfoPtr info,
                              int maxinfo,
                              unsigned char *cpumaps,
                              int maplen)
{
2396
    testDriverPtr privconn = domain->conn->privateData;
C
Cole Robinson 已提交
2397
    virDomainObjPtr privdom;
2398
    virDomainDefPtr def;
2399
    size_t i;
2400
    int hostcpus;
C
Cole Robinson 已提交
2401 2402 2403
    int ret = -1;
    struct timeval tv;
    unsigned long long statbase;
2404
    virBitmapPtr allcpumap = NULL;
C
Cole Robinson 已提交
2405

2406 2407
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
C
Cole Robinson 已提交
2408 2409

    if (!virDomainObjIsActive(privdom)) {
2410
        virReportError(VIR_ERR_OPERATION_INVALID,
2411
                       "%s", _("cannot list vcpus for an inactive domain"));
C
Cole Robinson 已提交
2412 2413 2414
        goto cleanup;
    }

2415
    def = privdom->def;
C
Cole Robinson 已提交
2416 2417

    if (gettimeofday(&tv, NULL) < 0) {
2418
        virReportSystemError(errno,
C
Cole Robinson 已提交
2419 2420 2421 2422 2423 2424 2425
                             "%s", _("getting time of day"));
        goto cleanup;
    }

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

    hostcpus = VIR_NODEINFO_MAXCPUS(privconn->nodeInfo);
2426 2427 2428 2429 2430
    if (!(allcpumap = virBitmapNew(hostcpus)))
        goto cleanup;

    virBitmapSetAll(allcpumap);

C
Cole Robinson 已提交
2431
    /* Clamp to actual number of vcpus */
2432 2433
    if (maxinfo > virDomainDefGetVcpus(privdom->def))
        maxinfo = virDomainDefGetVcpus(privdom->def);
C
Cole Robinson 已提交
2434

2435 2436
    memset(info, 0, sizeof(*info) * maxinfo);
    memset(cpumaps, 0, maxinfo * maplen);
C
Cole Robinson 已提交
2437

2438
    for (i = 0; i < maxinfo; i++) {
2439
        virDomainVcpuDefPtr vcpu = virDomainDefGetVcpu(def, i);
2440
        virBitmapPtr bitmap = NULL;
C
Cole Robinson 已提交
2441

2442 2443
        if (!vcpu->online)
            continue;
C
Cole Robinson 已提交
2444

2445 2446
        if (vcpu->cpumask)
            bitmap = vcpu->cpumask;
2447 2448 2449 2450
        else if (def->cpumask)
            bitmap = def->cpumask;
        else
            bitmap = allcpumap;
C
Cole Robinson 已提交
2451

2452 2453
        if (cpumaps)
            virBitmapToDataBuf(bitmap, VIR_GET_CPUMAP(cpumaps, maplen, i), maplen);
C
Cole Robinson 已提交
2454

2455 2456 2457
        info[i].number = i;
        info[i].state = VIR_VCPU_RUNNING;
        info[i].cpu = virBitmapLastSetBit(bitmap);
C
Cole Robinson 已提交
2458

2459 2460
        /* Fake an increasing cpu time value */
        info[i].cpuTime = statbase / 10;
C
Cole Robinson 已提交
2461 2462 2463
    }

    ret = maxinfo;
2464
 cleanup:
2465
    virBitmapFree(allcpumap);
2466
    virDomainObjEndAPI(&privdom);
C
Cole Robinson 已提交
2467 2468 2469
    return ret;
}

C
Cole Robinson 已提交
2470 2471 2472 2473 2474
static int testDomainPinVcpu(virDomainPtr domain,
                             unsigned int vcpu,
                             unsigned char *cpumap,
                             int maplen)
{
2475
    virDomainVcpuDefPtr vcpuinfo;
C
Cole Robinson 已提交
2476
    virDomainObjPtr privdom;
2477
    virDomainDefPtr def;
C
Cole Robinson 已提交
2478 2479
    int ret = -1;

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

2483 2484
    def = privdom->def;

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

2491 2492
    if (!(vcpuinfo = virDomainDefGetVcpu(def, vcpu)) ||
        !vcpuinfo->online) {
2493 2494 2495
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested vcpu '%d' is not present in the domain"),
                       vcpu);
C
Cole Robinson 已提交
2496 2497 2498
        goto cleanup;
    }

2499 2500 2501
    virBitmapFree(vcpuinfo->cpumask);

    if (!(vcpuinfo->cpumask = virBitmapNewData(cpumap, maplen)))
2502
        goto cleanup;
C
Cole Robinson 已提交
2503 2504

    ret = 0;
2505

2506
 cleanup:
2507
    virDomainObjEndAPI(&privdom);
C
Cole Robinson 已提交
2508 2509 2510
    return ret;
}

2511 2512 2513 2514 2515 2516 2517
static int
testDomainGetVcpuPinInfo(virDomainPtr dom,
                        int ncpumaps,
                        unsigned char *cpumaps,
                        int maplen,
                        unsigned int flags)
{
2518
    testDriverPtr driver = dom->conn->privateData;
2519 2520
    virDomainObjPtr privdom;
    virDomainDefPtr def;
2521
    int ret = -1;
2522 2523 2524 2525 2526 2527 2528

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

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

2529 2530 2531
    ret = virDomainDefGetVcpuPinInfoHelper(def, maplen, ncpumaps, cpumaps,
                                           VIR_NODEINFO_MAXCPUS(driver->nodeInfo),
                                           NULL);
2532 2533 2534 2535 2536 2537

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

2538 2539 2540 2541 2542 2543 2544 2545 2546 2547
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;
2548
    VIR_AUTOFREE(char *) new_dom_name = NULL;
2549 2550 2551

    virCheckFlags(0, -1);

2552 2553 2554 2555 2556 2557
    if (strchr(new_name, '/')) {
        virReportError(VIR_ERR_XML_ERROR,
                       _("name %s cannot contain '/'"), new_name);
        return -1;
    }

2558 2559 2560 2561 2562 2563 2564 2565
    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. */
2566 2567
    VIR_FREE(privdom->def->name);
    VIR_STEAL_PTR(privdom->def->name, new_dom_name);
2568 2569 2570 2571 2572 2573 2574

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

 cleanup:
2575 2576
    virObjectEventStateQueue(driver->eventState, event_old);
    virObjectEventStateQueue(driver->eventState, event_new);
2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623
    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;
}

2624
static char *testDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
2625
{
2626
    testDriverPtr privconn = domain->conn->privateData;
2627
    virDomainDefPtr def;
2628
    virDomainObjPtr privdom;
2629 2630
    char *ret = NULL;

2631
    virCheckFlags(VIR_DOMAIN_XML_COMMON_FLAGS, NULL);
2632

2633 2634
    if (!(privdom = testDomObjFromDomain(domain)))
        return NULL;
2635

2636 2637
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
2638

2639 2640
    ret = virDomainDefFormat(def, privconn->caps,
                             virDomainDefFormatConvertXMLFlags(flags));
2641

2642
    virDomainObjEndAPI(&privdom);
2643
    return ret;
2644
}
2645

2646 2647
static int testConnectNumOfDefinedDomains(virConnectPtr conn)
{
2648
    testDriverPtr privconn = conn->privateData;
2649

2650
    return virDomainObjListNumOfDomains(privconn->domains, false, NULL, NULL);
2651 2652
}

2653 2654
static int testConnectListDefinedDomains(virConnectPtr conn,
                                         char **const names,
2655 2656
                                         int maxnames)
{
2657
    testDriverPtr privconn = conn->privateData;
2658 2659

    memset(names, 0, sizeof(*names)*maxnames);
2660 2661
    return virDomainObjListGetInactiveNames(privconn->domains, names, maxnames,
                                            NULL, NULL);
2662 2663
}

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

    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
2677

2678
    if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
2679
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
2680

2681
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
2682
                                       NULL, parse_flags)) == NULL)
2683
        goto cleanup;
2684

2685 2686 2687
    if (virXMLCheckIllegalChars("name", def->name, "\n") < 0)
        goto cleanup;

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

2699
    event = virDomainEventLifecycleNewFromObj(dom,
2700
                                     VIR_DOMAIN_EVENT_DEFINED,
2701
                                     !oldDef ?
2702 2703
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
2704

2705
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
2706

2707
 cleanup:
2708
    virDomainDefFree(def);
2709
    virDomainDefFree(oldDef);
2710
    virDomainObjEndAPI(&dom);
2711
    virObjectEventStateQueue(privconn->eventState, event);
2712
    return ret;
2713 2714
}

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

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

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, NULL);

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

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

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

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

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

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

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

2762 2763 2764
    if (ret == 0) {
        virObjectEventPtr ev = NULL;
        ev = virDomainEventMetadataChangeNewFromObj(privdom, type, uri);
2765
        virObjectEventStateQueue(privconn->eventState, ev);
2766 2767
    }

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


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

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

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

2796
 cleanup:
2797
    virObjectUnlock(privconn);
2798
    return ret;
2799 2800
}

2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846
#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;
}
2847

2848 2849 2850 2851 2852 2853 2854
static unsigned long long
testNodeGetFreeMemory(virConnectPtr conn)
{
    testDriverPtr privconn = conn->privateData;
    unsigned int freeMem = 0;
    size_t i;

2855
    virObjectLock(privconn);
2856 2857 2858 2859

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

2860
    virObjectUnlock(privconn);
2861 2862 2863
    return freeMem;
}

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

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

2895 2896
    virCheckFlags(0, -1);

2897
    virObjectLock(privconn);
2898

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

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

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

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

2918
 cleanup:
2919
    virDomainObjEndAPI(&privdom);
2920
    virObjectEventStateQueue(privconn->eventState, event);
2921
    virObjectUnlock(privconn);
2922
    return ret;
2923 2924
}

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

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

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

2942

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

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

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

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

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

2982
    ret = 0;
2983

2984
 cleanup:
2985
    virDomainObjEndAPI(&privdom);
2986
    virObjectEventStateQueue(privconn->eventState, event);
2987
    return ret;
2988 2989
}

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

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

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

3003
    *autostart = privdom->autostart;
3004

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


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

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

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

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

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

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

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

3034 3035 3036
    return type;
}

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

3046 3047
    virCheckFlags(0, -1);

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

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

    *nparams = 1;
3058 3059
    ret = 0;

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

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

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

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

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

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

3100 3101
    ret = 0;

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

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

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

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

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

3132
    if (virDomainObjCheckActive(privdom) < 0)
3133 3134
        goto error;

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

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

3161 3162 3163 3164
static int
testDomainInterfaceStats(virDomainPtr domain,
                         const char *device,
                         virDomainInterfaceStatsPtr stats)
3165 3166 3167 3168
{
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
M
Michal Privoznik 已提交
3169 3170 3171
    virDomainNetDefPtr net = NULL;
    int ret = -1;

3172

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

3176
    if (virDomainObjCheckActive(privdom) < 0)
3177 3178
        goto error;

3179
    if (!(net = virDomainNetFind(privdom->def, device)))
3180 3181 3182
        goto error;

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

3205

3206 3207 3208 3209
static virNetworkObjPtr
testNetworkObjFindByUUID(testDriverPtr privconn,
                         const unsigned char *uuid)
{
3210
    virNetworkObjPtr obj;
3211 3212
    char uuidstr[VIR_UUID_STRING_BUFLEN];

3213
    if (!(obj = virNetworkObjFindByUUID(privconn->networks, uuid))) {
3214 3215 3216 3217 3218 3219
        virUUIDFormat(uuid, uuidstr);
        virReportError(VIR_ERR_NO_NETWORK,
                       _("no network with matching uuid '%s'"),
                       uuidstr);
    }

3220
    return obj;
3221 3222 3223
}


3224 3225 3226
static virNetworkPtr
testNetworkLookupByUUID(virConnectPtr conn,
                        const unsigned char *uuid)
3227
{
3228
    testDriverPtr privconn = conn->privateData;
3229
    virNetworkObjPtr obj;
3230
    virNetworkDefPtr def;
3231
    virNetworkPtr net = NULL;
3232

3233
    if (!(obj = testNetworkObjFindByUUID(privconn, uuid)))
3234
        goto cleanup;
3235
    def = virNetworkObjGetDef(obj);
3236

3237
    net = virGetNetwork(conn, def->name, def->uuid);
3238

3239
 cleanup:
3240 3241
    virNetworkObjEndAPI(&obj);
    return net;
3242
}
3243

3244 3245 3246 3247 3248

static virNetworkObjPtr
testNetworkObjFindByName(testDriverPtr privconn,
                         const char *name)
{
3249
    virNetworkObjPtr obj;
3250

3251
    if (!(obj = virNetworkObjFindByName(privconn->networks, name)))
3252 3253 3254 3255
        virReportError(VIR_ERR_NO_NETWORK,
                       _("no network with matching name '%s'"),
                       name);

3256
    return obj;
3257 3258 3259
}


3260 3261 3262
static virNetworkPtr
testNetworkLookupByName(virConnectPtr conn,
                        const char *name)
3263
{
3264
    testDriverPtr privconn = conn->privateData;
3265
    virNetworkObjPtr obj;
3266
    virNetworkDefPtr def;
3267
    virNetworkPtr net = NULL;
3268

3269
    if (!(obj = testNetworkObjFindByName(privconn, name)))
3270
        goto cleanup;
3271
    def = virNetworkObjGetDef(obj);
3272

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

3275
 cleanup:
3276 3277
    virNetworkObjEndAPI(&obj);
    return net;
3278 3279 3280
}


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

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

3292 3293 3294 3295

static int
testConnectListNetworks(virConnectPtr conn,
                        char **const names,
3296
                        int maxnames)
3297
{
3298
    testDriverPtr privconn = conn->privateData;
3299
    int n;
3300

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

3306 3307 3308

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

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

3318 3319 3320 3321

static int
testConnectListDefinedNetworks(virConnectPtr conn,
                               char **const names,
3322
                               int maxnames)
3323
{
3324
    testDriverPtr privconn = conn->privateData;
3325
    int n;
3326

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

3332

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

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

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

3345 3346 3347

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

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

3356 3357
    ret = virNetworkObjIsActive(obj);

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

3363 3364 3365

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

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

3374
    ret = virNetworkObjIsPersistent(obj);
3375

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


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

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

3395
    if (!(obj = virNetworkObjAssignDef(privconn->networks, newDef,
3396 3397
                                       VIR_NETWORK_OBJ_LIST_ADD_LIVE |
                                       VIR_NETWORK_OBJ_LIST_ADD_CHECK_LIVE)))
3398
        goto cleanup;
3399 3400
    newDef = NULL;
    def = virNetworkObjGetDef(obj);
3401
    virNetworkObjSetActive(obj, true);
3402

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

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

3409
 cleanup:
3410
    virNetworkDefFree(newDef);
3411
    virObjectEventStateQueue(privconn->eventState, event);
3412 3413
    virNetworkObjEndAPI(&obj);
    return net;
3414 3415
}

3416 3417 3418 3419

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

3428
    if ((newDef = virNetworkDefParseString(xml)) == NULL)
3429
        goto cleanup;
3430

3431
    if (!(obj = virNetworkObjAssignDef(privconn->networks, newDef, 0)))
3432
        goto cleanup;
3433 3434
    newDef = NULL;
    def = virNetworkObjGetDef(obj);
3435

3436
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
3437 3438
                                        VIR_NETWORK_EVENT_DEFINED,
                                        0);
3439

3440
    net = virGetNetwork(conn, def->name, def->uuid);
3441

3442
 cleanup:
3443
    virNetworkDefFree(newDef);
3444
    virObjectEventStateQueue(privconn->eventState, event);
3445 3446
    virNetworkObjEndAPI(&obj);
    return net;
3447 3448
}

3449 3450

static int
3451
testNetworkUndefine(virNetworkPtr net)
3452
{
3453 3454
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3455
    int ret = -1;
3456
    virObjectEventPtr event = NULL;
3457

3458
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3459
        goto cleanup;
3460

3461
    if (virNetworkObjIsActive(obj)) {
3462
        virReportError(VIR_ERR_OPERATION_INVALID,
3463
                       _("Network '%s' is still running"), net->name);
3464
        goto cleanup;
3465 3466
    }

3467
    event = virNetworkEventLifecycleNew(net->name, net->uuid,
3468 3469
                                        VIR_NETWORK_EVENT_UNDEFINED,
                                        0);
3470

3471
    virNetworkObjRemoveInactive(privconn->networks, obj);
3472
    ret = 0;
3473

3474
 cleanup:
3475
    virObjectEventStateQueue(privconn->eventState, event);
3476
    virNetworkObjEndAPI(&obj);
3477
    return ret;
3478 3479
}

3480

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

    virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
                  VIR_NETWORK_UPDATE_AFFECT_CONFIG,
                  -1);

3497
    if (!(obj = testNetworkObjFindByUUID(privconn, net->uuid)))
3498 3499 3500 3501 3502
        goto cleanup;

    /* VIR_NETWORK_UPDATE_AFFECT_CURRENT means "change LIVE if network
     * is active, else change CONFIG
    */
3503
    isActive = virNetworkObjIsActive(obj);
3504 3505 3506 3507 3508 3509 3510 3511 3512 3513
    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 */
3514
    if (virNetworkObjUpdate(obj, command, section, parentIndex, xml, flags) < 0)
3515 3516 3517
       goto cleanup;

    ret = 0;
3518
 cleanup:
3519
    virNetworkObjEndAPI(&obj);
3520 3521 3522
    return ret;
}

3523 3524

static int
3525
testNetworkCreate(virNetworkPtr net)
3526
{
3527 3528
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3529
    virNetworkDefPtr def;
3530
    int ret = -1;
3531
    virObjectEventPtr event = NULL;
3532

3533
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3534
        goto cleanup;
3535
    def = virNetworkObjGetDef(obj);
3536

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

3543
    virNetworkObjSetActive(obj, true);
3544
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
3545 3546
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3547
    ret = 0;
3548

3549
 cleanup:
3550
    virObjectEventStateQueue(privconn->eventState, event);
3551
    virNetworkObjEndAPI(&obj);
3552
    return ret;
3553 3554
}

3555 3556

static int
3557
testNetworkDestroy(virNetworkPtr net)
3558
{
3559 3560
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3561
    virNetworkDefPtr def;
3562
    int ret = -1;
3563
    virObjectEventPtr event = NULL;
3564

3565
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3566
        goto cleanup;
3567
    def = virNetworkObjGetDef(obj);
3568

3569
    virNetworkObjSetActive(obj, false);
3570
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
3571 3572
                                        VIR_NETWORK_EVENT_STOPPED,
                                        0);
3573
    if (!virNetworkObjIsPersistent(obj))
3574
        virNetworkObjRemoveInactive(privconn->networks, obj);
3575

3576 3577
    ret = 0;

3578
 cleanup:
3579
    virObjectEventStateQueue(privconn->eventState, event);
3580
    virNetworkObjEndAPI(&obj);
3581
    return ret;
3582 3583
}

3584 3585

static char *
3586
testNetworkGetXMLDesc(virNetworkPtr net,
3587
                      unsigned int flags)
3588
{
3589 3590
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3591
    char *ret = NULL;
3592

E
Eric Blake 已提交
3593 3594
    virCheckFlags(0, NULL);

3595
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3596
        goto cleanup;
3597

3598
    ret = virNetworkDefFormat(virNetworkObjGetDef(obj), flags);
3599

3600
 cleanup:
3601
    virNetworkObjEndAPI(&obj);
3602
    return ret;
3603 3604
}

3605 3606

static char *
3607
testNetworkGetBridgeName(virNetworkPtr net)
3608
{
3609
    testDriverPtr privconn = net->conn->privateData;
3610
    char *bridge = NULL;
3611
    virNetworkObjPtr obj;
3612
    virNetworkDefPtr def;
3613

3614
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3615
        goto cleanup;
3616
    def = virNetworkObjGetDef(obj);
3617

3618
    if (!(def->bridge)) {
3619 3620
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("network '%s' does not have a bridge name."),
3621
                       def->name);
3622 3623 3624
        goto cleanup;
    }

3625
    ignore_value(VIR_STRDUP(bridge, def->bridge));
3626

3627
 cleanup:
3628
    virNetworkObjEndAPI(&obj);
3629 3630 3631
    return bridge;
}

3632 3633

static int
3634
testNetworkGetAutostart(virNetworkPtr net,
3635
                        int *autostart)
3636
{
3637 3638
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3639
    int ret = -1;
3640

3641
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3642
        goto cleanup;
3643

3644
    *autostart = virNetworkObjIsAutostart(obj) ? 1 : 0;
3645 3646
    ret = 0;

3647
 cleanup:
3648
    virNetworkObjEndAPI(&obj);
3649
    return ret;
3650 3651
}

3652 3653

static int
3654
testNetworkSetAutostart(virNetworkPtr net,
3655
                        int autostart)
3656
{
3657 3658
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3659
    bool new_autostart = (autostart != 0);
3660
    int ret = -1;
3661

3662
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3663
        goto cleanup;
3664

3665 3666
    virNetworkObjSetAutostart(obj, new_autostart);

3667 3668
    ret = 0;

3669
 cleanup:
3670
    virNetworkObjEndAPI(&obj);
3671
    return ret;
3672
}
3673

C
Cole Robinson 已提交
3674

L
Laine Stump 已提交
3675 3676 3677 3678 3679
/*
 * Physical host interface routines
 */


3680 3681 3682 3683
static virInterfaceObjPtr
testInterfaceObjFindByName(testDriverPtr privconn,
                           const char *name)
{
3684
    virInterfaceObjPtr obj;
3685

3686
    virObjectLock(privconn);
3687
    obj = virInterfaceObjListFindByName(privconn->ifaces, name);
3688
    virObjectUnlock(privconn);
3689

3690
    if (!obj)
3691 3692 3693 3694
        virReportError(VIR_ERR_NO_INTERFACE,
                       _("no interface with matching name '%s'"),
                       name);

3695
    return obj;
3696 3697 3698
}


3699 3700
static int
testConnectNumOfInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3701
{
3702
    testDriverPtr privconn = conn->privateData;
3703
    int ninterfaces;
L
Laine Stump 已提交
3704

3705
    virObjectLock(privconn);
3706
    ninterfaces = virInterfaceObjListNumOfInterfaces(privconn->ifaces, true);
3707
    virObjectUnlock(privconn);
3708
    return ninterfaces;
L
Laine Stump 已提交
3709 3710
}

3711 3712 3713 3714 3715

static int
testConnectListInterfaces(virConnectPtr conn,
                          char **const names,
                          int maxnames)
L
Laine Stump 已提交
3716
{
3717
    testDriverPtr privconn = conn->privateData;
3718
    int nnames;
L
Laine Stump 已提交
3719

3720
    virObjectLock(privconn);
3721 3722
    nnames = virInterfaceObjListGetNames(privconn->ifaces, true,
                                         names, maxnames);
3723
    virObjectUnlock(privconn);
L
Laine Stump 已提交
3724

3725
    return nnames;
L
Laine Stump 已提交
3726 3727
}

3728 3729 3730

static int
testConnectNumOfDefinedInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3731
{
3732
    testDriverPtr privconn = conn->privateData;
3733
    int ninterfaces;
L
Laine Stump 已提交
3734

3735
    virObjectLock(privconn);
3736
    ninterfaces = virInterfaceObjListNumOfInterfaces(privconn->ifaces, false);
3737
    virObjectUnlock(privconn);
3738
    return ninterfaces;
L
Laine Stump 已提交
3739 3740
}

3741 3742 3743 3744 3745

static int
testConnectListDefinedInterfaces(virConnectPtr conn,
                                 char **const names,
                                 int maxnames)
L
Laine Stump 已提交
3746
{
3747
    testDriverPtr privconn = conn->privateData;
3748
    int nnames;
L
Laine Stump 已提交
3749

3750
    virObjectLock(privconn);
3751 3752
    nnames = virInterfaceObjListGetNames(privconn->ifaces, false,
                                         names, maxnames);
3753
    virObjectUnlock(privconn);
L
Laine Stump 已提交
3754

3755
    return nnames;
L
Laine Stump 已提交
3756 3757
}

3758

3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772
static int
testConnectListAllInterfaces(virConnectPtr conn,
                             virInterfacePtr **ifaces,
                             unsigned int flags)
{
    testDriverPtr privconn = conn->privateData;

    virCheckFlags(VIR_CONNECT_LIST_INTERFACES_FILTERS_ACTIVE, -1);

    return virInterfaceObjListExport(conn, privconn->ifaces, ifaces,
                                     NULL, flags);
}


3773 3774 3775
static virInterfacePtr
testInterfaceLookupByName(virConnectPtr conn,
                          const char *name)
L
Laine Stump 已提交
3776
{
3777
    testDriverPtr privconn = conn->privateData;
3778
    virInterfaceObjPtr obj;
3779
    virInterfaceDefPtr def;
L
Laine Stump 已提交
3780 3781
    virInterfacePtr ret = NULL;

3782
    if (!(obj = testInterfaceObjFindByName(privconn, name)))
3783
        return NULL;
3784
    def = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
3785

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

3788
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
3789 3790 3791
    return ret;
}

3792 3793 3794 3795

static virInterfacePtr
testInterfaceLookupByMACString(virConnectPtr conn,
                               const char *mac)
L
Laine Stump 已提交
3796
{
3797
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3798
    int ifacect;
3799
    char *ifacenames[] = { NULL, NULL };
L
Laine Stump 已提交
3800 3801
    virInterfacePtr ret = NULL;

3802
    virObjectLock(privconn);
3803 3804
    ifacect = virInterfaceObjListFindByMACString(privconn->ifaces, mac,
                                                 ifacenames, 2);
3805
    virObjectUnlock(privconn);
L
Laine Stump 已提交
3806 3807

    if (ifacect == 0) {
3808 3809
        virReportError(VIR_ERR_NO_INTERFACE,
                       _("no interface with matching mac '%s'"), mac);
L
Laine Stump 已提交
3810 3811 3812 3813
        goto cleanup;
    }

    if (ifacect > 1) {
3814
        virReportError(VIR_ERR_MULTIPLE_INTERFACES, NULL);
L
Laine Stump 已提交
3815 3816 3817
        goto cleanup;
    }

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

3820
 cleanup:
3821 3822
    VIR_FREE(ifacenames[0]);
    VIR_FREE(ifacenames[1]);
L
Laine Stump 已提交
3823 3824 3825
    return ret;
}

3826 3827 3828

static int
testInterfaceIsActive(virInterfacePtr iface)
3829
{
3830
    testDriverPtr privconn = iface->conn->privateData;
3831 3832 3833
    virInterfaceObjPtr obj;
    int ret = -1;

3834
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
3835
        return -1;
3836

3837 3838
    ret = virInterfaceObjIsActive(obj);

3839
    virInterfaceObjEndAPI(&obj);
3840 3841 3842
    return ret;
}

3843 3844 3845 3846

static int
testInterfaceChangeBegin(virConnectPtr conn,
                         unsigned int flags)
3847
{
3848
    testDriverPtr privconn = conn->privateData;
3849 3850
    int ret = -1;

E
Eric Blake 已提交
3851 3852
    virCheckFlags(0, -1);

3853
    virObjectLock(privconn);
3854
    if (privconn->transaction_running) {
3855
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3856
                       _("there is another transaction running."));
3857 3858 3859 3860 3861
        goto cleanup;
    }

    privconn->transaction_running = true;

3862
    if (!(privconn->backupIfaces = virInterfaceObjListClone(privconn->ifaces)))
3863 3864 3865
        goto cleanup;

    ret = 0;
3866
 cleanup:
3867
    virObjectUnlock(privconn);
3868 3869 3870
    return ret;
}

3871 3872 3873 3874

static int
testInterfaceChangeCommit(virConnectPtr conn,
                          unsigned int flags)
3875
{
3876
    testDriverPtr privconn = conn->privateData;
3877 3878
    int ret = -1;

E
Eric Blake 已提交
3879 3880
    virCheckFlags(0, -1);

3881
    virObjectLock(privconn);
3882 3883

    if (!privconn->transaction_running) {
3884
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3885 3886
                       _("no transaction running, "
                         "nothing to be committed."));
3887 3888 3889
        goto cleanup;
    }

3890
    virObjectUnref(privconn->backupIfaces);
3891 3892 3893 3894
    privconn->transaction_running = false;

    ret = 0;

3895
 cleanup:
3896
    virObjectUnlock(privconn);
3897 3898 3899 3900

    return ret;
}

3901 3902 3903 3904

static int
testInterfaceChangeRollback(virConnectPtr conn,
                            unsigned int flags)
3905
{
3906
    testDriverPtr privconn = conn->privateData;
3907 3908
    int ret = -1;

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

3911
    virObjectLock(privconn);
3912 3913

    if (!privconn->transaction_running) {
3914
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3915 3916
                       _("no transaction running, "
                         "nothing to rollback."));
3917 3918 3919
        goto cleanup;
    }

3920
    virObjectUnref(privconn->ifaces);
3921 3922
    privconn->ifaces = privconn->backupIfaces;
    privconn->backupIfaces = NULL;
3923 3924 3925 3926 3927

    privconn->transaction_running = false;

    ret = 0;

3928
 cleanup:
3929
    virObjectUnlock(privconn);
3930 3931
    return ret;
}
3932

3933 3934 3935 3936

static char *
testInterfaceGetXMLDesc(virInterfacePtr iface,
                        unsigned int flags)
L
Laine Stump 已提交
3937
{
3938
    testDriverPtr privconn = iface->conn->privateData;
3939
    virInterfaceObjPtr obj;
3940
    virInterfaceDefPtr def;
L
Laine Stump 已提交
3941 3942
    char *ret = NULL;

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

3945
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
3946
        return NULL;
3947
    def = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
3948

3949
    ret = virInterfaceDefFormat(def);
L
Laine Stump 已提交
3950

3951
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
3952 3953 3954 3955
    return ret;
}


3956 3957 3958 3959
static virInterfacePtr
testInterfaceDefineXML(virConnectPtr conn,
                       const char *xmlStr,
                       unsigned int flags)
L
Laine Stump 已提交
3960
{
3961
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3962
    virInterfaceDefPtr def;
3963
    virInterfaceObjPtr obj = NULL;
3964
    virInterfaceDefPtr objdef;
L
Laine Stump 已提交
3965 3966
    virInterfacePtr ret = NULL;

E
Eric Blake 已提交
3967 3968
    virCheckFlags(0, NULL);

3969
    virObjectLock(privconn);
3970
    if ((def = virInterfaceDefParseString(xmlStr)) == NULL)
L
Laine Stump 已提交
3971 3972
        goto cleanup;

3973
    if ((obj = virInterfaceObjListAssignDef(privconn->ifaces, def)) == NULL)
L
Laine Stump 已提交
3974 3975
        goto cleanup;
    def = NULL;
3976
    objdef = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
3977

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

3980
 cleanup:
L
Laine Stump 已提交
3981
    virInterfaceDefFree(def);
3982
    virInterfaceObjEndAPI(&obj);
3983
    virObjectUnlock(privconn);
L
Laine Stump 已提交
3984 3985 3986
    return ret;
}

3987 3988 3989

static int
testInterfaceUndefine(virInterfacePtr iface)
L
Laine Stump 已提交
3990
{
3991
    testDriverPtr privconn = iface->conn->privateData;
3992
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
3993

3994
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
3995
        return -1;
L
Laine Stump 已提交
3996

3997
    virInterfaceObjListRemove(privconn->ifaces, obj);
3998
    virObjectUnref(obj);
L
Laine Stump 已提交
3999

4000
    return 0;
L
Laine Stump 已提交
4001 4002
}

4003 4004 4005 4006

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

E
Eric Blake 已提交
4012 4013
    virCheckFlags(0, -1);

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

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

4022
    virInterfaceObjSetActive(obj, true);
L
Laine Stump 已提交
4023 4024
    ret = 0;

4025
 cleanup:
4026
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
4027 4028 4029
    return ret;
}

4030 4031 4032 4033

static int
testInterfaceDestroy(virInterfacePtr iface,
                     unsigned int flags)
L
Laine Stump 已提交
4034
{
4035
    testDriverPtr privconn = iface->conn->privateData;
4036
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
4037 4038
    int ret = -1;

E
Eric Blake 已提交
4039 4040
    virCheckFlags(0, -1);

4041
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
4042
        return -1;
L
Laine Stump 已提交
4043

4044
    if (!virInterfaceObjIsActive(obj)) {
4045
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
4046 4047 4048
        goto cleanup;
    }

4049
    virInterfaceObjSetActive(obj, false);
L
Laine Stump 已提交
4050 4051
    ret = 0;

4052
 cleanup:
4053
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
4054 4055 4056 4057 4058
    return ret;
}



C
Cole Robinson 已提交
4059 4060 4061 4062
/*
 * Storage Driver routines
 */

4063
static int
4064
testStoragePoolObjSetDefaults(virStoragePoolObjPtr obj)
4065
{
4066
    char *configFile;
4067
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4068

4069 4070 4071
    def->capacity = defaultPoolCap;
    def->allocation = defaultPoolAlloc;
    def->available = defaultPoolCap - defaultPoolAlloc;
C
Cole Robinson 已提交
4072

4073 4074 4075 4076 4077
    if (VIR_STRDUP(configFile, "") < 0)
        return -1;

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

4080

4081 4082 4083 4084
static virStoragePoolObjPtr
testStoragePoolObjFindByName(testDriverPtr privconn,
                             const char *name)
{
4085
    virStoragePoolObjPtr obj;
4086

4087
    virObjectLock(privconn);
4088
    obj = virStoragePoolObjFindByName(privconn->pools, name);
4089
    virObjectUnlock(privconn);
4090

4091
    if (!obj)
4092 4093 4094 4095
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       name);

4096
    return obj;
4097 4098 4099
}


4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111
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);
4112
        virStoragePoolObjEndAPI(&obj);
4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131
        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);
4132
        virStoragePoolObjEndAPI(&obj);
4133 4134 4135 4136 4137 4138 4139
        return NULL;
    }

    return obj;
}


4140 4141 4142 4143
static virStoragePoolObjPtr
testStoragePoolObjFindByUUID(testDriverPtr privconn,
                             const unsigned char *uuid)
{
4144
    virStoragePoolObjPtr obj;
4145 4146
    char uuidstr[VIR_UUID_STRING_BUFLEN];

4147
    virObjectLock(privconn);
4148
    obj = virStoragePoolObjFindByUUID(privconn->pools, uuid);
4149
    virObjectUnlock(privconn);
4150

4151
    if (!obj) {
4152 4153 4154 4155 4156 4157
        virUUIDFormat(uuid, uuidstr);
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching uuid '%s'"),
                       uuidstr);
    }

4158
    return obj;
4159 4160 4161
}


C
Cole Robinson 已提交
4162 4163
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
4164 4165
                            const unsigned char *uuid)
{
4166
    testDriverPtr privconn = conn->privateData;
4167
    virStoragePoolObjPtr obj;
4168
    virStoragePoolDefPtr def;
4169
    virStoragePoolPtr pool = NULL;
C
Cole Robinson 已提交
4170

4171
    if (!(obj = testStoragePoolObjFindByUUID(privconn, uuid)))
4172
        return NULL;
4173
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4174

4175
    pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
4176

4177
    virStoragePoolObjEndAPI(&obj);
4178
    return pool;
C
Cole Robinson 已提交
4179 4180
}

4181

C
Cole Robinson 已提交
4182 4183
static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
4184 4185
                            const char *name)
{
4186
    testDriverPtr privconn = conn->privateData;
4187
    virStoragePoolObjPtr obj;
4188
    virStoragePoolDefPtr def;
4189
    virStoragePoolPtr pool = NULL;
C
Cole Robinson 已提交
4190

4191
    if (!(obj = testStoragePoolObjFindByName(privconn, name)))
4192
        return NULL;
4193
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4194

4195
    pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
4196

4197
    virStoragePoolObjEndAPI(&obj);
4198
    return pool;
C
Cole Robinson 已提交
4199 4200
}

4201

C
Cole Robinson 已提交
4202
static virStoragePoolPtr
4203 4204
testStoragePoolLookupByVolume(virStorageVolPtr vol)
{
C
Cole Robinson 已提交
4205 4206 4207
    return testStoragePoolLookupByName(vol->conn, vol->pool);
}

4208

C
Cole Robinson 已提交
4209
static int
4210 4211
testConnectNumOfStoragePools(virConnectPtr conn)
{
4212
    testDriverPtr privconn = conn->privateData;
4213
    int numActive = 0;
C
Cole Robinson 已提交
4214

4215
    virObjectLock(privconn);
4216
    numActive = virStoragePoolObjNumOfStoragePools(privconn->pools, conn,
4217
                                                   true, NULL);
4218
    virObjectUnlock(privconn);
C
Cole Robinson 已提交
4219 4220 4221 4222

    return numActive;
}

4223

C
Cole Robinson 已提交
4224
static int
4225 4226
testConnectListStoragePools(virConnectPtr conn,
                            char **const names,
4227
                            int maxnames)
4228
{
4229
    testDriverPtr privconn = conn->privateData;
4230
    int n = 0;
C
Cole Robinson 已提交
4231

4232
    virObjectLock(privconn);
4233
    n = virStoragePoolObjGetNames(privconn->pools, conn, true, NULL,
4234
                                  names, maxnames);
4235
    virObjectUnlock(privconn);
C
Cole Robinson 已提交
4236 4237 4238 4239

    return n;
}

4240

C
Cole Robinson 已提交
4241
static int
4242 4243
testConnectNumOfDefinedStoragePools(virConnectPtr conn)
{
4244
    testDriverPtr privconn = conn->privateData;
4245
    int numInactive = 0;
C
Cole Robinson 已提交
4246

4247
    virObjectLock(privconn);
4248
    numInactive = virStoragePoolObjNumOfStoragePools(privconn->pools, conn,
4249
                                                     false, NULL);
4250
    virObjectUnlock(privconn);
C
Cole Robinson 已提交
4251 4252 4253 4254

    return numInactive;
}

4255

C
Cole Robinson 已提交
4256
static int
4257 4258
testConnectListDefinedStoragePools(virConnectPtr conn,
                                   char **const names,
4259
                                   int maxnames)
4260
{
4261
    testDriverPtr privconn = conn->privateData;
4262
    int n = 0;
C
Cole Robinson 已提交
4263

4264
    virObjectLock(privconn);
4265
    n = virStoragePoolObjGetNames(privconn->pools, conn, false, NULL,
4266
                                  names, maxnames);
4267
    virObjectUnlock(privconn);
C
Cole Robinson 已提交
4268 4269 4270 4271

    return n;
}

4272

4273
static int
4274 4275 4276
testConnectListAllStoragePools(virConnectPtr conn,
                               virStoragePoolPtr **pools,
                               unsigned int flags)
4277
{
4278
    testDriverPtr privconn = conn->privateData;
4279 4280 4281 4282
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

4283
    virObjectLock(privconn);
4284
    ret = virStoragePoolObjListExport(conn, privconn->pools, pools,
4285
                                      NULL, flags);
4286
    virObjectUnlock(privconn);
4287 4288 4289

    return ret;
}
C
Cole Robinson 已提交
4290

4291 4292 4293

static int
testStoragePoolIsActive(virStoragePoolPtr pool)
4294
{
4295
    testDriverPtr privconn = pool->conn->privateData;
4296 4297 4298
    virStoragePoolObjPtr obj;
    int ret = -1;

4299
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
4300
        goto cleanup;
4301

4302 4303
    ret = virStoragePoolObjIsActive(obj);

4304
 cleanup:
4305
    if (obj)
4306
        virStoragePoolObjEndAPI(&obj);
4307 4308 4309
    return ret;
}

4310 4311 4312

static int
testStoragePoolIsPersistent(virStoragePoolPtr pool)
4313
{
4314
    testDriverPtr privconn = pool->conn->privateData;
4315 4316 4317
    virStoragePoolObjPtr obj;
    int ret = -1;

4318
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
4319
        return -1;
4320

4321
    ret = virStoragePoolObjGetConfigFile(obj) ? 1 : 0;
4322

4323
    virStoragePoolObjEndAPI(&obj);
4324 4325 4326 4327
    return ret;
}


C
Cole Robinson 已提交
4328
static int
4329 4330
testStoragePoolCreate(virStoragePoolPtr pool,
                      unsigned int flags)
E
Eric Blake 已提交
4331
{
4332
    testDriverPtr privconn = pool->conn->privateData;
4333
    virStoragePoolObjPtr obj;
4334
    virObjectEventPtr event = NULL;
4335

E
Eric Blake 已提交
4336 4337
    virCheckFlags(0, -1);

4338 4339
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
4340

4341
    virStoragePoolObjSetActive(obj, true);
4342 4343 4344 4345

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

4347
    virObjectEventStateQueue(privconn->eventState, event);
4348
    virStoragePoolObjEndAPI(&obj);
4349
    return 0;
C
Cole Robinson 已提交
4350 4351
}

4352

C
Cole Robinson 已提交
4353
static char *
4354 4355 4356 4357
testConnectFindStoragePoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type,
                                  const char *srcSpec,
                                  unsigned int flags)
C
Cole Robinson 已提交
4358
{
4359 4360
    int pool_type;
    char *ret = NULL;
4361
    VIR_AUTOPTR(virStoragePoolSource) source = NULL;
4362

E
Eric Blake 已提交
4363 4364
    virCheckFlags(0, NULL);

4365 4366
    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
4367 4368
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
4369
        return NULL;
4370 4371 4372
    }

    if (srcSpec) {
4373
        source = virStoragePoolDefParseSourceString(srcSpec, pool_type);
4374
        if (!source)
4375
            return NULL;
4376 4377 4378 4379 4380
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
4381
        ignore_value(VIR_STRDUP(ret, defaultPoolSourcesLogicalXML));
4382
        return ret;
4383 4384

    case VIR_STORAGE_POOL_NETFS:
4385
        if (!source || !source->hosts[0].name) {
4386 4387
            virReportError(VIR_ERR_INVALID_ARG,
                           "%s", _("hostname must be specified for netfs sources"));
4388
            return NULL;
4389 4390
        }

4391 4392
        ignore_value(virAsprintf(&ret, defaultPoolSourcesNetFSXML,
                                 source->hosts[0].name));
4393
        return ret;
4394 4395

    default:
4396 4397
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source discovery"), type);
4398 4399
    }

4400
    return NULL;
C
Cole Robinson 已提交
4401 4402 4403
}


4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425
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;
4426
    virNodeDeviceObjEndAPI(&obj);
4427 4428 4429 4430 4431

    return 0;
}


C
Cole Robinson 已提交
4432
static virStoragePoolPtr
4433 4434 4435
testStoragePoolCreateXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4436
{
4437
    testDriverPtr privconn = conn->privateData;
4438
    virStoragePoolObjPtr obj = NULL;
4439
    virStoragePoolDefPtr def;
4440
    virStoragePoolPtr pool = NULL;
4441
    virObjectEventPtr event = NULL;
4442
    VIR_AUTOPTR(virStoragePoolDef) newDef = NULL;
C
Cole Robinson 已提交
4443

E
Eric Blake 已提交
4444 4445
    virCheckFlags(0, NULL);

4446
    virObjectLock(privconn);
4447
    if (!(newDef = virStoragePoolDefParseString(xml)))
4448
        goto cleanup;
C
Cole Robinson 已提交
4449

4450
    if (!(obj = virStoragePoolObjAssignDef(privconn->pools, newDef, true)))
4451
        goto cleanup;
4452 4453
    newDef = NULL;
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4454

4455
    if (def->source.adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
4456 4457 4458 4459 4460
        /* 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,
4461 4462
                            def->source.adapter.data.fchost.wwnn,
                            def->source.adapter.data.fchost.wwpn) < 0) {
4463
            virStoragePoolObjRemove(privconn->pools, obj);
4464
            virObjectUnref(obj);
4465
            obj = NULL;
4466 4467 4468 4469
            goto cleanup;
        }
    }

4470
    if (testStoragePoolObjSetDefaults(obj) == -1) {
4471
        virStoragePoolObjRemove(privconn->pools, obj);
4472
        virObjectUnref(obj);
4473
        obj = NULL;
4474
        goto cleanup;
C
Cole Robinson 已提交
4475
    }
4476 4477 4478 4479

    /* *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 */
4480
    virStoragePoolObjSetConfigFile(obj, NULL);
4481

4482
    virStoragePoolObjSetActive(obj, true);
C
Cole Robinson 已提交
4483

4484
    event = virStoragePoolEventLifecycleNew(def->name, def->uuid,
4485 4486 4487
                                            VIR_STORAGE_POOL_EVENT_STARTED,
                                            0);

4488
    pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
4489

4490
 cleanup:
4491
    virObjectEventStateQueue(privconn->eventState, event);
4492
    virStoragePoolObjEndAPI(&obj);
4493
    virObjectUnlock(privconn);
4494
    return pool;
C
Cole Robinson 已提交
4495 4496
}

4497

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

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

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

4516 4517 4518
    newDef->capacity = defaultPoolCap;
    newDef->allocation = defaultPoolAlloc;
    newDef->available = defaultPoolCap - defaultPoolAlloc;
C
Cole Robinson 已提交
4519

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

4525
    event = virStoragePoolEventLifecycleNew(def->name, def->uuid,
4526 4527 4528
                                            VIR_STORAGE_POOL_EVENT_DEFINED,
                                            0);

4529
    if (testStoragePoolObjSetDefaults(obj) == -1) {
4530
        virStoragePoolObjRemove(privconn->pools, obj);
4531
        virObjectUnref(obj);
4532
        obj = NULL;
4533
        goto cleanup;
C
Cole Robinson 已提交
4534 4535
    }

4536
    pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
4537

4538
 cleanup:
4539
    virObjectEventStateQueue(privconn->eventState, event);
4540
    virStoragePoolObjEndAPI(&obj);
4541
    virObjectUnlock(privconn);
4542
    return pool;
C
Cole Robinson 已提交
4543 4544
}

4545

C
Cole Robinson 已提交
4546
static int
4547 4548
testStoragePoolUndefine(virStoragePoolPtr pool)
{
4549
    testDriverPtr privconn = pool->conn->privateData;
4550
    virStoragePoolObjPtr obj;
4551
    virObjectEventPtr event = NULL;
4552

4553 4554
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
4555

4556 4557 4558 4559
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_UNDEFINED,
                                            0);

4560
    virStoragePoolObjRemove(privconn->pools, obj);
4561
    virObjectUnref(obj);
C
Cole Robinson 已提交
4562

4563
    virObjectEventStateQueue(privconn->eventState, event);
4564
    return 0;
C
Cole Robinson 已提交
4565 4566
}

4567

C
Cole Robinson 已提交
4568
static int
4569
testStoragePoolBuild(virStoragePoolPtr pool,
E
Eric Blake 已提交
4570 4571
                     unsigned int flags)
{
4572
    testDriverPtr privconn = pool->conn->privateData;
4573
    virStoragePoolObjPtr obj;
4574
    virObjectEventPtr event = NULL;
4575

E
Eric Blake 已提交
4576 4577
    virCheckFlags(0, -1);

4578 4579
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
4580

4581 4582 4583 4584
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_CREATED,
                                            0);

4585
    virStoragePoolObjEndAPI(&obj);
4586

4587
    virObjectEventStateQueue(privconn->eventState, event);
4588
    return 0;
C
Cole Robinson 已提交
4589 4590 4591
}


4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606
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 */
4607 4608
    if (!(obj = virNodeDeviceObjListFindByName(privconn->devs,
                                               "scsi_host12"))) {
4609 4610
        virReportError(VIR_ERR_NO_NODE_DEVICE, "%s",
                       _("no node device with matching name 'scsi_host12'"));
4611
        return -1;
4612 4613 4614 4615 4616 4617
    }

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

4618
    virNodeDeviceObjListRemove(privconn->devs, obj);
4619
    virObjectUnref(obj);
4620

4621
    virObjectEventStateQueue(privconn->eventState, event);
4622
    return 0;
4623 4624 4625
}


C
Cole Robinson 已提交
4626
static int
4627 4628
testStoragePoolDestroy(virStoragePoolPtr pool)
{
4629
    testDriverPtr privconn = pool->conn->privateData;
4630
    virStoragePoolObjPtr obj;
4631
    virStoragePoolDefPtr def;
4632
    int ret = -1;
4633
    virObjectEventPtr event = NULL;
4634

4635
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
4636
        return -1;
4637
    def = virStoragePoolObjGetDef(obj);
4638

4639
    virStoragePoolObjSetActive(obj, false);
4640

4641
    if (def->source.adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
4642
        if (testDestroyVport(privconn,
4643 4644
                             def->source.adapter.data.fchost.wwnn,
                             def->source.adapter.data.fchost.wwpn) < 0)
4645 4646 4647
            goto cleanup;
    }

4648 4649
    event = virStoragePoolEventLifecycleNew(def->name,
                                            def->uuid,
4650 4651
                                            VIR_STORAGE_POOL_EVENT_STOPPED,
                                            0);
C
Cole Robinson 已提交
4652

4653
    if (!(virStoragePoolObjGetConfigFile(obj))) {
4654
        virStoragePoolObjRemove(privconn->pools, obj);
4655
        virObjectUnref(obj);
4656
        obj = NULL;
4657
    }
4658
    ret = 0;
C
Cole Robinson 已提交
4659

4660
 cleanup:
4661
    virObjectEventStateQueue(privconn->eventState, event);
4662
    virStoragePoolObjEndAPI(&obj);
4663
    return ret;
C
Cole Robinson 已提交
4664 4665 4666 4667
}


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

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

4677 4678
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
4679

4680 4681 4682 4683
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_DELETED,
                                            0);

4684
    virObjectEventStateQueue(privconn->eventState, event);
4685

4686
    virStoragePoolObjEndAPI(&obj);
4687
    return 0;
C
Cole Robinson 已提交
4688 4689 4690 4691
}


static int
4692
testStoragePoolRefresh(virStoragePoolPtr pool,
E
Eric Blake 已提交
4693 4694
                       unsigned int flags)
{
4695
    testDriverPtr privconn = pool->conn->privateData;
4696
    virStoragePoolObjPtr obj;
4697
    virObjectEventPtr event = NULL;
4698

E
Eric Blake 已提交
4699 4700
    virCheckFlags(0, -1);

4701 4702
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return -1;
4703

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

4706
    virObjectEventStateQueue(privconn->eventState, event);
4707
    virStoragePoolObjEndAPI(&obj);
4708
    return 0;
C
Cole Robinson 已提交
4709 4710 4711 4712
}


static int
4713
testStoragePoolGetInfo(virStoragePoolPtr pool,
4714 4715
                       virStoragePoolInfoPtr info)
{
4716
    testDriverPtr privconn = pool->conn->privateData;
4717
    virStoragePoolObjPtr obj;
4718
    virStoragePoolDefPtr def;
4719

4720
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
4721
        return -1;
4722
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4723 4724

    memset(info, 0, sizeof(virStoragePoolInfo));
4725
    if (virStoragePoolObjIsActive(obj))
C
Cole Robinson 已提交
4726 4727 4728
        info->state = VIR_STORAGE_POOL_RUNNING;
    else
        info->state = VIR_STORAGE_POOL_INACTIVE;
4729 4730 4731
    info->capacity = def->capacity;
    info->allocation = def->allocation;
    info->available = def->available;
C
Cole Robinson 已提交
4732

4733
    virStoragePoolObjEndAPI(&obj);
4734
    return 0;
C
Cole Robinson 已提交
4735 4736
}

4737

C
Cole Robinson 已提交
4738
static char *
4739
testStoragePoolGetXMLDesc(virStoragePoolPtr pool,
E
Eric Blake 已提交
4740 4741
                          unsigned int flags)
{
4742
    testDriverPtr privconn = pool->conn->privateData;
4743
    virStoragePoolObjPtr obj;
4744
    char *ret = NULL;
4745

E
Eric Blake 已提交
4746 4747
    virCheckFlags(0, NULL);

4748
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
4749
        return NULL;
4750

4751
    ret = virStoragePoolDefFormat(virStoragePoolObjGetDef(obj));
4752

4753
    virStoragePoolObjEndAPI(&obj);
4754
    return ret;
C
Cole Robinson 已提交
4755 4756
}

4757

C
Cole Robinson 已提交
4758
static int
4759
testStoragePoolGetAutostart(virStoragePoolPtr pool,
4760 4761
                            int *autostart)
{
4762
    testDriverPtr privconn = pool->conn->privateData;
4763
    virStoragePoolObjPtr obj;
4764

4765
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
4766
        return -1;
C
Cole Robinson 已提交
4767

4768
    if (!virStoragePoolObjGetConfigFile(obj))
C
Cole Robinson 已提交
4769
        *autostart = 0;
4770
    else
4771
        *autostart = virStoragePoolObjIsAutostart(obj) ? 1 : 0;
C
Cole Robinson 已提交
4772

4773
    virStoragePoolObjEndAPI(&obj);
4774
    return 0;
C
Cole Robinson 已提交
4775 4776
}

4777

C
Cole Robinson 已提交
4778
static int
4779
testStoragePoolSetAutostart(virStoragePoolPtr pool,
4780 4781
                            int autostart)
{
4782
    testDriverPtr privconn = pool->conn->privateData;
4783
    virStoragePoolObjPtr obj;
4784
    bool new_autostart = (autostart != 0);
4785
    int ret = -1;
4786

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

4790
    if (!virStoragePoolObjGetConfigFile(obj)) {
4791 4792
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("pool has no config file"));
4793
        goto cleanup;
C
Cole Robinson 已提交
4794 4795
    }

4796
    virStoragePoolObjSetAutostart(obj, new_autostart);
4797 4798
    ret = 0;

4799
 cleanup:
4800
    virStoragePoolObjEndAPI(&obj);
4801
    return ret;
C
Cole Robinson 已提交
4802 4803 4804 4805
}


static int
4806 4807
testStoragePoolNumOfVolumes(virStoragePoolPtr pool)
{
4808
    testDriverPtr privconn = pool->conn->privateData;
4809
    virStoragePoolObjPtr obj;
4810
    int ret = -1;
4811

4812 4813
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
4814

4815
    ret = virStoragePoolObjNumOfVolumes(obj, pool->conn, NULL);
4816

4817
    virStoragePoolObjEndAPI(&obj);
4818
    return ret;
C
Cole Robinson 已提交
4819 4820
}

4821

C
Cole Robinson 已提交
4822
static int
4823
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4824
                           char **const names,
4825 4826
                           int maxnames)
{
4827
    testDriverPtr privconn = pool->conn->privateData;
4828
    virStoragePoolObjPtr obj;
4829
    int n = -1;
4830

4831
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
4832
        return -1;
4833

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

4836
    virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
4837 4838 4839
    return n;
}

4840

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

    virCheckFlags(0, -1);

4852
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
4853
        return -1;
4854

4855
    if (!virStoragePoolObjIsActive(obj)) {
4856 4857 4858 4859 4860
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("storage pool is not active"));
        goto cleanup;
    }

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

 cleanup:
4864
    virStoragePoolObjEndAPI(&obj);
4865 4866 4867

    return ret;
}
C
Cole Robinson 已提交
4868

4869

4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884
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 已提交
4885
static virStorageVolPtr
4886
testStorageVolLookupByName(virStoragePoolPtr pool,
4887
                           const char *name)
4888
{
4889
    testDriverPtr privconn = pool->conn->privateData;
4890
    virStoragePoolObjPtr obj;
4891
    virStoragePoolDefPtr def;
4892
    virStorageVolDefPtr privvol;
4893
    virStorageVolPtr ret = NULL;
4894

4895 4896
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return NULL;
4897
    def = virStoragePoolObjGetDef(obj);
4898

4899
    if (!(privvol = testStorageVolDefFindByName(obj, name)))
4900
        goto cleanup;
C
Cole Robinson 已提交
4901

4902
    ret = virGetStorageVol(pool->conn, def->name,
4903 4904
                           privvol->name, privvol->key,
                           NULL, NULL);
4905

4906
 cleanup:
4907
    virStoragePoolObjEndAPI(&obj);
4908
    return ret;
C
Cole Robinson 已提交
4909 4910 4911
}


4912 4913 4914 4915 4916 4917 4918 4919 4920 4921
struct storageVolLookupData {
    const char *key;
    const char *path;
    virStorageVolDefPtr voldef;
};

static bool
testStorageVolLookupByKeyCallback(virStoragePoolObjPtr obj,
                                  const void *opaque)
{
4922
    struct storageVolLookupData *data = (struct storageVolLookupData *)opaque;
4923 4924 4925 4926 4927 4928 4929 4930

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

    return !!data->voldef;
}


C
Cole Robinson 已提交
4931
static virStorageVolPtr
4932
testStorageVolLookupByKey(virConnectPtr conn,
4933 4934
                          const char *key)
{
4935
    testDriverPtr privconn = conn->privateData;
4936
    virStoragePoolObjPtr obj;
4937
    virStoragePoolDefPtr def;
4938
    struct storageVolLookupData data = {
4939
        .key = key, .voldef = NULL };
4940
    virStorageVolPtr vol = NULL;
C
Cole Robinson 已提交
4941

4942
    virObjectLock(privconn);
4943
    if ((obj = virStoragePoolObjListSearch(privconn->pools,
4944 4945
                                           testStorageVolLookupByKeyCallback,
                                           &data)) && data.voldef) {
4946
        def = virStoragePoolObjGetDef(obj);
4947 4948 4949
        vol = virGetStorageVol(conn, def->name,
                               data.voldef->name, data.voldef->key,
                               NULL, NULL);
4950
        virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
4951
    }
4952
    virObjectUnlock(privconn);
C
Cole Robinson 已提交
4953

4954
    if (!vol)
4955 4956
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching key '%s'"), key);
4957

4958 4959 4960 4961 4962 4963 4964 4965
    return vol;
}


static bool
testStorageVolLookupByPathCallback(virStoragePoolObjPtr obj,
                                   const void *opaque)
{
4966
    struct storageVolLookupData *data = (struct storageVolLookupData *)opaque;
4967 4968 4969 4970 4971

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

    return !!data->voldef;
C
Cole Robinson 已提交
4972 4973
}

4974

C
Cole Robinson 已提交
4975
static virStorageVolPtr
4976
testStorageVolLookupByPath(virConnectPtr conn,
4977 4978
                           const char *path)
{
4979
    testDriverPtr privconn = conn->privateData;
4980
    virStoragePoolObjPtr obj;
4981
    virStoragePoolDefPtr def;
4982
    struct storageVolLookupData data = {
4983
        .path = path, .voldef = NULL };
4984
    virStorageVolPtr vol = NULL;
C
Cole Robinson 已提交
4985

4986
    virObjectLock(privconn);
4987
    if ((obj = virStoragePoolObjListSearch(privconn->pools,
4988 4989
                                           testStorageVolLookupByPathCallback,
                                           &data)) && data.voldef) {
4990
        def = virStoragePoolObjGetDef(obj);
4991 4992 4993
        vol = virGetStorageVol(conn, def->name,
                               data.voldef->name, data.voldef->key,
                               NULL, NULL);
4994
        virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
4995
    }
4996
    virObjectUnlock(privconn);
C
Cole Robinson 已提交
4997

4998
    if (!vol)
4999 5000
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching path '%s'"), path);
5001

5002
    return vol;
C
Cole Robinson 已提交
5003 5004
}

5005

C
Cole Robinson 已提交
5006
static virStorageVolPtr
5007 5008 5009
testStorageVolCreateXML(virStoragePoolPtr pool,
                        const char *xmldesc,
                        unsigned int flags)
E
Eric Blake 已提交
5010
{
5011
    testDriverPtr privconn = pool->conn->privateData;
5012
    virStoragePoolObjPtr obj;
5013
    virStoragePoolDefPtr def;
5014
    virStorageVolPtr ret = NULL;
5015
    VIR_AUTOPTR(virStorageVolDef) privvol = NULL;
5016

E
Eric Blake 已提交
5017 5018
    virCheckFlags(0, NULL);

5019 5020
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return NULL;
5021
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
5022

5023
    privvol = virStorageVolDefParseString(def, xmldesc, 0);
5024
    if (privvol == NULL)
5025
        goto cleanup;
5026

5027
    if (virStorageVolDefFindByName(obj, privvol->name)) {
5028 5029
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
5030
        goto cleanup;
C
Cole Robinson 已提交
5031 5032 5033
    }

    /* Make sure enough space */
5034 5035
    if ((def->allocation + privvol->target.allocation) >
         def->capacity) {
5036 5037 5038
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
5039
        goto cleanup;
C
Cole Robinson 已提交
5040 5041
    }

5042
    if (virAsprintf(&privvol->target.path, "%s/%s",
5043
                    def->target.path, privvol->name) < 0)
5044
        goto cleanup;
C
Cole Robinson 已提交
5045

5046
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
5047
        virStoragePoolObjAddVol(obj, privvol) < 0)
5048
        goto cleanup;
C
Cole Robinson 已提交
5049

5050 5051
    def->allocation += privvol->target.allocation;
    def->available = (def->capacity - def->allocation);
C
Cole Robinson 已提交
5052

5053
    ret = virGetStorageVol(pool->conn, def->name,
5054 5055
                           privvol->name, privvol->key,
                           NULL, NULL);
5056
    privvol = NULL;
5057

5058
 cleanup:
5059
    virStoragePoolObjEndAPI(&obj);
5060
    return ret;
C
Cole Robinson 已提交
5061 5062
}

5063

5064
static virStorageVolPtr
5065 5066 5067 5068
testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
                            const char *xmldesc,
                            virStorageVolPtr clonevol,
                            unsigned int flags)
E
Eric Blake 已提交
5069
{
5070
    testDriverPtr privconn = pool->conn->privateData;
5071
    virStoragePoolObjPtr obj;
5072
    virStoragePoolDefPtr def;
5073
    virStorageVolDefPtr origvol = NULL;
5074
    virStorageVolPtr ret = NULL;
5075
    VIR_AUTOPTR(virStorageVolDef) privvol = NULL;
5076

E
Eric Blake 已提交
5077 5078
    virCheckFlags(0, NULL);

5079 5080
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return NULL;
5081
    def = virStoragePoolObjGetDef(obj);
5082

5083
    privvol = virStorageVolDefParseString(def, xmldesc, 0);
5084 5085 5086
    if (privvol == NULL)
        goto cleanup;

5087
    if (virStorageVolDefFindByName(obj, privvol->name)) {
5088 5089
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
5090 5091 5092
        goto cleanup;
    }

5093
    origvol = virStorageVolDefFindByName(obj, clonevol->name);
5094
    if (!origvol) {
5095 5096 5097
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       clonevol->name);
5098 5099 5100 5101
        goto cleanup;
    }

    /* Make sure enough space */
5102
    if ((def->allocation + privvol->target.allocation) > def->capacity) {
5103 5104 5105
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
5106 5107
        goto cleanup;
    }
5108
    def->available = (def->capacity - def->allocation);
5109

5110
    if (virAsprintf(&privvol->target.path, "%s/%s",
5111
                    def->target.path, privvol->name) < 0)
5112 5113
        goto cleanup;

5114
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
5115
        virStoragePoolObjAddVol(obj, privvol) < 0)
5116 5117
        goto cleanup;

5118 5119
    def->allocation += privvol->target.allocation;
    def->available = (def->capacity - def->allocation);
5120

5121
    ret = virGetStorageVol(pool->conn, def->name,
5122 5123
                           privvol->name, privvol->key,
                           NULL, NULL);
5124 5125
    privvol = NULL;

5126
 cleanup:
5127
    virStoragePoolObjEndAPI(&obj);
5128 5129 5130
    return ret;
}

5131

C
Cole Robinson 已提交
5132
static int
5133 5134
testStorageVolDelete(virStorageVolPtr vol,
                     unsigned int flags)
E
Eric Blake 已提交
5135
{
5136
    testDriverPtr privconn = vol->conn->privateData;
5137
    virStoragePoolObjPtr obj;
5138
    virStoragePoolDefPtr def;
5139
    virStorageVolDefPtr privvol;
5140
    int ret = -1;
C
Cole Robinson 已提交
5141

E
Eric Blake 已提交
5142 5143
    virCheckFlags(0, -1);

5144 5145
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return -1;
5146
    def = virStoragePoolObjGetDef(obj);
5147

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

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

5154
    virStoragePoolObjRemoveVol(obj, privvol);
C
Cole Robinson 已提交
5155

5156
    ret = 0;
C
Cole Robinson 已提交
5157

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


5164 5165
static int
testStorageVolumeTypeForPool(int pooltype)
5166
{
5167
    switch (pooltype) {
C
Cole Robinson 已提交
5168 5169 5170 5171 5172 5173 5174 5175 5176
        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;
    }
}

5177

C
Cole Robinson 已提交
5178
static int
5179
testStorageVolGetInfo(virStorageVolPtr vol,
5180 5181
                      virStorageVolInfoPtr info)
{
5182
    testDriverPtr privconn = vol->conn->privateData;
5183
    virStoragePoolObjPtr obj;
5184
    virStoragePoolDefPtr def;
5185
    virStorageVolDefPtr privvol;
5186
    int ret = -1;
5187

5188 5189
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return -1;
5190
    def = virStoragePoolObjGetDef(obj);
5191

5192
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
5193
        goto cleanup;
5194

C
Cole Robinson 已提交
5195
    memset(info, 0, sizeof(*info));
5196
    info->type = testStorageVolumeTypeForPool(def->type);
5197 5198
    info->capacity = privvol->target.capacity;
    info->allocation = privvol->target.allocation;
5199
    ret = 0;
C
Cole Robinson 已提交
5200

5201
 cleanup:
5202
    virStoragePoolObjEndAPI(&obj);
5203
    return ret;
C
Cole Robinson 已提交
5204 5205
}

5206

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

E
Eric Blake 已提交
5216 5217
    virCheckFlags(0, NULL);

5218 5219
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return NULL;
5220

5221
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
5222
        goto cleanup;
C
Cole Robinson 已提交
5223

5224
    ret = virStorageVolDefFormat(virStoragePoolObjGetDef(obj), privvol);
5225

5226
 cleanup:
5227
    virStoragePoolObjEndAPI(&obj);
5228
    return ret;
C
Cole Robinson 已提交
5229 5230
}

5231

C
Cole Robinson 已提交
5232
static char *
5233 5234
testStorageVolGetPath(virStorageVolPtr vol)
{
5235
    testDriverPtr privconn = vol->conn->privateData;
5236
    virStoragePoolObjPtr obj;
5237
    virStorageVolDefPtr privvol;
5238
    char *ret = NULL;
5239

5240 5241
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return NULL;
5242

5243
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
5244
        goto cleanup;
5245

5246
    ignore_value(VIR_STRDUP(ret, privvol->target.path));
5247

5248
 cleanup:
5249
    virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
5250 5251 5252
    return ret;
}

5253

5254
/* Node device implementations */
5255

5256 5257 5258 5259 5260 5261
static virNodeDeviceObjPtr
testNodeDeviceObjFindByName(testDriverPtr driver,
                            const char *name)
{
    virNodeDeviceObjPtr obj;

5262
    if (!(obj = virNodeDeviceObjListFindByName(driver->devs, name)))
5263 5264 5265 5266 5267 5268 5269 5270
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       name);

    return obj;
}


5271 5272 5273
static int
testNodeNumOfDevices(virConnectPtr conn,
                     const char *cap,
E
Eric Blake 已提交
5274
                     unsigned int flags)
5275
{
5276
    testDriverPtr driver = conn->privateData;
5277

E
Eric Blake 已提交
5278 5279
    virCheckFlags(0, -1);

5280
    return virNodeDeviceObjListNumOfDevices(driver->devs, conn, cap, NULL);
5281 5282
}

5283

5284 5285 5286 5287 5288
static int
testNodeListDevices(virConnectPtr conn,
                    const char *cap,
                    char **const names,
                    int maxnames,
E
Eric Blake 已提交
5289
                    unsigned int flags)
5290
{
5291
    testDriverPtr driver = conn->privateData;
5292

E
Eric Blake 已提交
5293 5294
    virCheckFlags(0, -1);

5295 5296
    return virNodeDeviceObjListGetNames(driver->devs, conn, NULL,
                                        cap, names, maxnames);
5297 5298
}

5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310
static int
testConnectListAllNodeDevices(virConnectPtr conn,
                              virNodeDevicePtr **devices,
                              unsigned int flags)
{
    testDriverPtr driver = conn->privateData;

    virCheckFlags(VIR_CONNECT_LIST_NODE_DEVICES_FILTERS_CAP, -1);

    return virNodeDeviceObjListExport(conn, driver->devs, devices,
                                      NULL, flags);
}
5311

5312 5313 5314
static virNodeDevicePtr
testNodeDeviceLookupByName(virConnectPtr conn, const char *name)
{
5315
    testDriverPtr driver = conn->privateData;
5316
    virNodeDeviceObjPtr obj;
5317
    virNodeDeviceDefPtr def;
5318 5319
    virNodeDevicePtr ret = NULL;

5320
    if (!(obj = testNodeDeviceObjFindByName(driver, name)))
5321
        return NULL;
5322
    def = virNodeDeviceObjGetDef(obj);
5323

5324
    if ((ret = virGetNodeDevice(conn, name))) {
5325
        if (VIR_STRDUP(ret->parentName, def->parent) < 0) {
5326
            virObjectUnref(ret);
5327 5328
            ret = NULL;
        }
5329
    }
5330

5331
    virNodeDeviceObjEndAPI(&obj);
5332 5333 5334 5335
    return ret;
}

static char *
5336
testNodeDeviceGetXMLDesc(virNodeDevicePtr dev,
E
Eric Blake 已提交
5337
                         unsigned int flags)
5338
{
5339
    testDriverPtr driver = dev->conn->privateData;
5340 5341 5342
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

E
Eric Blake 已提交
5343 5344
    virCheckFlags(0, NULL);

5345
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5346
        return NULL;
5347

5348
    ret = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(obj));
5349

5350
    virNodeDeviceObjEndAPI(&obj);
5351 5352 5353 5354 5355 5356
    return ret;
}

static char *
testNodeDeviceGetParent(virNodeDevicePtr dev)
{
5357
    testDriverPtr driver = dev->conn->privateData;
5358
    virNodeDeviceObjPtr obj;
5359
    virNodeDeviceDefPtr def;
5360 5361
    char *ret = NULL;

5362
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5363
        return NULL;
5364
    def = virNodeDeviceObjGetDef(obj);
5365

5366 5367
    if (def->parent) {
        ignore_value(VIR_STRDUP(ret, def->parent));
5368
    } else {
5369 5370
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no parent for this device"));
5371 5372
    }

5373
    virNodeDeviceObjEndAPI(&obj);
5374 5375 5376
    return ret;
}

5377

5378 5379 5380
static int
testNodeDeviceNumOfCaps(virNodeDevicePtr dev)
{
5381
    testDriverPtr driver = dev->conn->privateData;
5382
    virNodeDeviceObjPtr obj;
5383
    virNodeDeviceDefPtr def;
5384 5385 5386
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;

5387
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5388
        return -1;
5389
    def = virNodeDeviceObjGetDef(obj);
5390

5391
    for (caps = def->caps; caps; caps = caps->next)
5392 5393
        ++ncaps;

5394
    virNodeDeviceObjEndAPI(&obj);
5395
    return ncaps;
5396 5397 5398 5399 5400 5401
}


static int
testNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
5402
    testDriverPtr driver = dev->conn->privateData;
5403
    virNodeDeviceObjPtr obj;
5404
    virNodeDeviceDefPtr def;
5405 5406 5407
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;

5408
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5409
        return -1;
5410
    def = virNodeDeviceObjGetDef(obj);
5411

5412
    for (caps = def->caps; caps && ncaps < maxnames; caps = caps->next) {
5413 5414 5415 5416
        if (VIR_STRDUP(names[ncaps],
                       virNodeDevCapTypeToString(caps->data.type)) < 0)
            goto error;
        ncaps++;
5417 5418
    }

5419
    virNodeDeviceObjEndAPI(&obj);
5420 5421 5422 5423 5424
    return ncaps;

 error:
    while (--ncaps >= 0)
        VIR_FREE(names[ncaps]);
5425
    virNodeDeviceObjEndAPI(&obj);
5426
    return -1;
5427 5428
}

5429

5430 5431
static virNodeDeviceObjPtr
testNodeDeviceMockCreateVport(testDriverPtr driver,
5432
                              const char *wwnn,
5433
                              const char *wwpn)
5434
{
5435
    virNodeDeviceDefPtr def = NULL;
5436
    virNodeDevCapsDefPtr caps;
5437
    virNodeDeviceObjPtr obj = NULL, objcopy = NULL;
5438
    virNodeDeviceDefPtr objdef;
5439
    virObjectEventPtr event = NULL;
5440
    VIR_AUTOFREE(char *) xml = NULL;
5441

5442 5443 5444 5445 5446 5447 5448 5449 5450
    /* 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. */
5451 5452
    if (!(objcopy = virNodeDeviceObjListFindByName(driver->devs,
                                                   "scsi_host11")))
5453 5454
        goto cleanup;

5455
    xml = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(objcopy));
5456
    virNodeDeviceObjEndAPI(&objcopy);
5457 5458 5459 5460
    if (!xml)
        goto cleanup;

    if (!(def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL)))
5461 5462
        goto cleanup;

5463
    VIR_FREE(def->name);
5464
    if (VIR_STRDUP(def->name, "scsi_host12") < 0)
5465 5466
        goto cleanup;

5467 5468 5469
    /* 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. */
5470 5471
    caps = def->caps;
    while (caps) {
5472
        if (caps->data.type != VIR_NODE_DEV_CAP_SCSI_HOST)
5473 5474
            continue;

5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488
        /* 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++;
        }
5489 5490 5491
        caps = caps->next;
    }

5492
    if (!(obj = virNodeDeviceObjListAssignDef(driver->devs, def)))
5493
        goto cleanup;
5494
    virNodeDeviceObjSetSkipUpdateCaps(obj, true);
5495
    def = NULL;
5496
    objdef = virNodeDeviceObjGetDef(obj);
5497

5498
    event = virNodeDeviceEventLifecycleNew(objdef->name,
5499 5500
                                           VIR_NODE_DEVICE_EVENT_CREATED,
                                           0);
5501
    virObjectEventStateQueue(driver->eventState, event);
5502 5503

 cleanup:
5504 5505
    virNodeDeviceDefFree(def);
    return obj;
5506 5507 5508 5509 5510 5511 5512 5513 5514 5515
}


static virNodeDevicePtr
testNodeDeviceCreateXML(virConnectPtr conn,
                        const char *xmlDesc,
                        unsigned int flags)
{
    testDriverPtr driver = conn->privateData;
    virNodeDeviceDefPtr def = NULL;
5516 5517
    virNodeDevicePtr dev = NULL, ret = NULL;
    virNodeDeviceObjPtr obj = NULL;
5518
    virNodeDeviceDefPtr objdef;
5519 5520
    VIR_AUTOFREE(char *) wwnn = NULL;
    VIR_AUTOFREE(char *) wwpn = NULL;
5521 5522 5523 5524 5525 5526

    virCheckFlags(0, NULL);

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

5527 5528 5529
    /* We run this simply for validation - it essentially validates that
     * the input XML either has a wwnn/wwpn or virNodeDevCapSCSIHostParseXML
     * generated a wwnn/wwpn */
5530 5531 5532
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) < 0)
        goto cleanup;

5533 5534 5535
    /* 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. */
5536
    if (virNodeDeviceObjListGetParentHost(driver->devs, def) < 0)
5537 5538 5539 5540
        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
5541 5542 5543
     * 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 */
5544 5545
    if (!(obj = testNodeDeviceMockCreateVport(driver, wwnn, wwpn)))
        goto cleanup;
5546
    objdef = virNodeDeviceObjGetDef(obj);
5547

5548
    if (!(dev = virGetNodeDevice(conn, objdef->name)))
5549 5550
        goto cleanup;

5551 5552
    VIR_FREE(dev->parentName);
    if (VIR_STRDUP(dev->parentName, def->parent) < 0)
5553 5554
        goto cleanup;

5555
    VIR_STEAL_PTR(ret, dev);
5556

5557
 cleanup:
5558
    virNodeDeviceObjEndAPI(&obj);
5559
    virNodeDeviceDefFree(def);
5560 5561
    virObjectUnref(dev);
    return ret;
5562 5563 5564 5565 5566 5567
}

static int
testNodeDeviceDestroy(virNodeDevicePtr dev)
{
    int ret = 0;
5568
    testDriverPtr driver = dev->conn->privateData;
5569
    virNodeDeviceObjPtr obj = NULL;
5570
    virNodeDeviceObjPtr parentobj = NULL;
5571
    virNodeDeviceDefPtr def;
5572
    virObjectEventPtr event = NULL;
5573 5574
    VIR_AUTOFREE(char *) wwnn = NULL;
    VIR_AUTOFREE(char *) wwpn = NULL;
5575

5576
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5577
        return -1;
5578
    def = virNodeDeviceObjGetDef(obj);
5579

5580
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) == -1)
5581
        goto cleanup;
5582

5583 5584 5585 5586
    /* 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 */
5587
    virObjectUnlock(obj);
5588

5589 5590 5591 5592 5593 5594
    /* 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);
5595
        virObjectLock(obj);
5596
        goto cleanup;
5597
    }
5598
    virNodeDeviceObjEndAPI(&parentobj);
5599

5600 5601 5602 5603
    event = virNodeDeviceEventLifecycleNew(dev->name,
                                           VIR_NODE_DEVICE_EVENT_DELETED,
                                           0);

5604
    virObjectLock(obj);
5605
    virNodeDeviceObjListRemove(driver->devs, obj);
5606
    virObjectUnref(obj);
5607
    obj = NULL;
5608

5609
 cleanup:
5610
    virNodeDeviceObjEndAPI(&obj);
5611
    virObjectEventStateQueue(driver->eventState, event);
5612 5613 5614
    return ret;
}

5615 5616

/* Domain event implementations */
5617
static int
5618 5619 5620 5621
testConnectDomainEventRegister(virConnectPtr conn,
                               virConnectDomainEventCallback callback,
                               void *opaque,
                               virFreeCallback freecb)
5622
{
5623
    testDriverPtr driver = conn->privateData;
5624
    int ret = 0;
5625

5626
    if (virDomainEventStateRegister(conn, driver->eventState,
5627 5628
                                    callback, opaque, freecb) < 0)
        ret = -1;
5629 5630 5631 5632

    return ret;
}

5633

5634
static int
5635 5636
testConnectDomainEventDeregister(virConnectPtr conn,
                                 virConnectDomainEventCallback callback)
5637
{
5638
    testDriverPtr driver = conn->privateData;
5639
    int ret = 0;
5640

5641
    if (virDomainEventStateDeregister(conn, driver->eventState,
5642 5643
                                      callback) < 0)
        ret = -1;
5644 5645 5646 5647

    return ret;
}

5648 5649

static int
5650 5651 5652 5653 5654 5655
testConnectDomainEventRegisterAny(virConnectPtr conn,
                                  virDomainPtr dom,
                                  int eventID,
                                  virConnectDomainEventGenericCallback callback,
                                  void *opaque,
                                  virFreeCallback freecb)
5656
{
5657
    testDriverPtr driver = conn->privateData;
5658 5659
    int ret;

5660
    if (virDomainEventStateRegisterID(conn, driver->eventState,
5661 5662
                                      dom, eventID,
                                      callback, opaque, freecb, &ret) < 0)
5663
        ret = -1;
5664 5665 5666 5667 5668

    return ret;
}

static int
5669 5670
testConnectDomainEventDeregisterAny(virConnectPtr conn,
                                    int callbackID)
5671
{
5672
    testDriverPtr driver = conn->privateData;
5673
    int ret = 0;
5674

5675
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5676
                                        callbackID, true) < 0)
5677
        ret = -1;
5678 5679 5680 5681 5682

    return ret;
}


5683 5684 5685 5686 5687 5688 5689 5690
static int
testConnectNetworkEventRegisterAny(virConnectPtr conn,
                                   virNetworkPtr net,
                                   int eventID,
                                   virConnectNetworkEventGenericCallback callback,
                                   void *opaque,
                                   virFreeCallback freecb)
{
5691
    testDriverPtr driver = conn->privateData;
5692 5693
    int ret;

5694
    if (virNetworkEventStateRegisterID(conn, driver->eventState,
5695
                                       net, eventID, callback,
5696 5697 5698 5699 5700 5701 5702 5703 5704 5705
                                       opaque, freecb, &ret) < 0)
        ret = -1;

    return ret;
}

static int
testConnectNetworkEventDeregisterAny(virConnectPtr conn,
                                     int callbackID)
{
5706
    testDriverPtr driver = conn->privateData;
5707
    int ret = 0;
5708

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

    return ret;
}

5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742
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,
5743
                                        callbackID, true) < 0)
5744 5745 5746 5747 5748
        ret = -1;

    return ret;
}

5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775
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,
5776
                                        callbackID, true) < 0)
5777 5778 5779 5780 5781
        ret = -1;

    return ret;
}

5782 5783 5784
static int testConnectListAllDomains(virConnectPtr conn,
                                     virDomainPtr **domains,
                                     unsigned int flags)
5785
{
5786
    testDriverPtr privconn = conn->privateData;
5787

O
Osier Yang 已提交
5788
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
5789

5790 5791
    return virDomainObjListExport(privconn->domains, conn, domains,
                                  NULL, flags);
5792 5793
}

5794
static int
P
Peter Krempa 已提交
5795
testNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,
5796 5797 5798 5799 5800 5801 5802
                  unsigned char **cpumap,
                  unsigned int *online,
                  unsigned int flags)
{
    virCheckFlags(0, -1);

    if (cpumap) {
5803
        if (VIR_ALLOC_N(*cpumap, 1) < 0)
P
Peter Krempa 已提交
5804
            return -1;
5805 5806 5807 5808 5809 5810
        *cpumap[0] = 0x15;
    }

    if (online)
        *online = 3;

P
Peter Krempa 已提交
5811
    return  8;
5812 5813
}

5814 5815 5816 5817 5818 5819 5820 5821 5822 5823
static char *
testDomainScreenshot(virDomainPtr dom ATTRIBUTE_UNUSED,
                     virStreamPtr st,
                     unsigned int screen ATTRIBUTE_UNUSED,
                     unsigned int flags)
{
    char *ret = NULL;

    virCheckFlags(0, NULL);

5824
    if (VIR_STRDUP(ret, "image/png") < 0)
5825 5826
        return NULL;

D
Daniel P. Berrange 已提交
5827
    if (virFDStreamOpenFile(st, PKGDATADIR "/test-screenshot.png", 0, 0, O_RDONLY) < 0)
5828 5829 5830 5831 5832
        VIR_FREE(ret);

    return ret;
}

5833 5834
static int
testConnectGetCPUModelNames(virConnectPtr conn ATTRIBUTE_UNUSED,
J
Jiri Denemark 已提交
5835
                            const char *archName,
5836 5837 5838
                            char ***models,
                            unsigned int flags)
{
J
Jiri Denemark 已提交
5839 5840
    virArch arch;

5841
    virCheckFlags(0, -1);
J
Jiri Denemark 已提交
5842 5843 5844 5845 5846 5847 5848 5849

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

J
Jiri Denemark 已提交
5850
    return virCPUGetModels(arch, models);
5851
}
5852

C
Cole Robinson 已提交
5853 5854 5855
static int
testDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
5856
    testDriverPtr privconn = dom->conn->privateData;
C
Cole Robinson 已提交
5857
    virDomainObjPtr vm = NULL;
5858
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
5859 5860 5861 5862 5863 5864
    int ret = -1;

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

5865 5866
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5867

5868
    if (virDomainObjCheckActive(vm) < 0)
C
Cole Robinson 已提交
5869 5870 5871 5872 5873 5874 5875 5876 5877
        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);
5878
    event = virDomainEventLifecycleNewFromObj(vm,
C
Cole Robinson 已提交
5879 5880 5881 5882 5883
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
    vm->hasManagedSave = true;

    ret = 0;
5884
 cleanup:
5885
    virDomainObjEndAPI(&vm);
5886
    virObjectEventStateQueue(privconn->eventState, event);
C
Cole Robinson 已提交
5887 5888 5889 5890 5891 5892 5893 5894 5895

    return ret;
}


static int
testDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm;
5896
    int ret;
C
Cole Robinson 已提交
5897 5898 5899

    virCheckFlags(0, -1);

5900 5901
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5902 5903

    ret = vm->hasManagedSave;
5904

5905
    virDomainObjEndAPI(&vm);
C
Cole Robinson 已提交
5906 5907 5908 5909 5910 5911 5912 5913 5914 5915
    return ret;
}

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

    virCheckFlags(0, -1);

5916 5917
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5918 5919

    vm->hasManagedSave = false;
5920

5921
    virDomainObjEndAPI(&vm);
5922
    return 0;
C
Cole Robinson 已提交
5923 5924 5925
}


5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959
/*
 * 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;
5960
    int n;
5961 5962 5963 5964 5965

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5966
        return -1;
5967 5968 5969

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

5970
    virDomainObjEndAPI(&vm);
5971 5972 5973 5974 5975 5976 5977 5978 5979 5980
    return n;
}

static int
testDomainSnapshotListNames(virDomainPtr domain,
                            char **names,
                            int nameslen,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
5981
    int n;
5982 5983 5984 5985 5986

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5987
        return -1;
5988 5989 5990 5991

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

5992
    virDomainObjEndAPI(&vm);
5993 5994 5995 5996 5997 5998 5999 6000 6001
    return n;
}

static int
testDomainListAllSnapshots(virDomainPtr domain,
                           virDomainSnapshotPtr **snaps,
                           unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6002
    int n;
6003 6004 6005 6006 6007

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6008
        return -1;
6009 6010 6011

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

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

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

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

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

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

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

6062
 cleanup:
6063
    virDomainObjEndAPI(&vm);
6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079
    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)))
6080
        return -1;
6081 6082 6083 6084 6085 6086 6087

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

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

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

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

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

6112
 cleanup:
6113
    virDomainObjEndAPI(&vm);
6114 6115 6116 6117 6118 6119 6120 6121
    return snapshot;
}

static int
testDomainHasCurrentSnapshot(virDomainPtr domain,
                             unsigned int flags)
{
    virDomainObjPtr vm;
6122
    int ret;
6123 6124 6125 6126

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6127
        return -1;
6128 6129 6130

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

6131
    virDomainObjEndAPI(&vm);
6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145
    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)))
6146
        return NULL;
6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159

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

6160
 cleanup:
6161
    virDomainObjEndAPI(&vm);
6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174
    return parent;
}

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

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
6175
        return NULL;
6176 6177 6178 6179 6180 6181 6182 6183 6184

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

6185
 cleanup:
6186
    virDomainObjEndAPI(&vm);
6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197
    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];
6198
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6199 6200 6201 6202

    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6203
        return NULL;
6204 6205 6206 6207 6208 6209

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

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

6210
    xml = virDomainSnapshotDefFormat(uuidstr, snap->def, privconn->caps,
6211
                                     privconn->xmlopt,
6212 6213
                                     virDomainDefFormatConvertXMLFlags(flags),
                                     0);
6214

6215
 cleanup:
6216
    virDomainObjEndAPI(&vm);
6217 6218 6219 6220 6221 6222 6223 6224
    return xml;
}

static int
testDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6225
    int ret;
6226 6227 6228 6229

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6230
        return -1;
6231 6232 6233 6234

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

6235
    virDomainObjEndAPI(&vm);
6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249
    return ret;
}


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

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6250
        return -1;
6251

C
Cole Robinson 已提交
6252
    if (!testSnapObjFromSnapshot(vm, snapshot))
6253 6254 6255 6256
        goto cleanup;

    ret = 1;

6257
 cleanup:
6258
    virDomainObjEndAPI(&vm);
6259 6260 6261
    return ret;
}

6262 6263 6264 6265 6266 6267
static int
testDomainSnapshotAlignDisks(virDomainObjPtr vm,
                             virDomainSnapshotDefPtr def,
                             unsigned int flags)
{
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
E
Eric Blake 已提交
6268
    bool align_match = true;
6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296

    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)
{
6297
    testDriverPtr privconn = domain->conn->privateData;
6298 6299 6300 6301
    virDomainObjPtr vm = NULL;
    virDomainSnapshotDefPtr def = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr snapshot = NULL;
6302
    virObjectEventPtr event = NULL;
6303 6304
    bool update_current = true;
    bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
6305 6306 6307 6308 6309 6310 6311 6312
    unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;

    /*
     * DISK_ONLY: Not implemented yet
     * REUSE_EXT: Not implemented yet
     *
     * NO_METADATA: Explicitly not implemented
     *
6313
     * REDEFINE + CURRENT: Implemented
6314 6315 6316 6317 6318 6319
     * HALT: Implemented
     * QUIESCE: Nothing to do
     * ATOMIC: Nothing to do
     * LIVE: Nothing to do
     */
    virCheckFlags(
6320 6321
        VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
        VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
6322 6323 6324 6325 6326
        VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
        VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
        VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
        VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, NULL);

6327 6328 6329 6330 6331
    if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)))
        update_current = false;
    if (redefine)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;

6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346
    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;

6347
    if (redefine) {
C
Cole Robinson 已提交
6348
        if (virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
6349
                                          privconn->xmlopt,
C
Cole Robinson 已提交
6350
                                          &update_current, flags) < 0)
6351 6352 6353 6354 6355
            goto cleanup;
    } else {
        if (!(def->dom = virDomainDefCopy(vm->def,
                                          privconn->caps,
                                          privconn->xmlopt,
6356
                                          NULL,
6357 6358
                                          true)))
            goto cleanup;
6359

6360
        if (testDomainSnapshotAlignDisks(vm, def, flags) < 0)
6361 6362 6363
            goto cleanup;
    }

6364 6365 6366 6367
    if (!snap) {
        if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
            goto cleanup;
        def = NULL;
6368 6369
    }

6370 6371 6372 6373 6374 6375 6376 6377 6378 6379
    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);
6380
            event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
6381 6382 6383
                                    VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
        }
    }
6384 6385

    snapshot = virGetDomainSnapshot(domain, snap->def->name);
6386
 cleanup:
6387 6388 6389
    if (vm) {
        if (snapshot) {
            virDomainSnapshotObjPtr other;
6390 6391
            if (update_current)
                vm->current_snapshot = snap;
6392 6393 6394 6395 6396 6397 6398
            other = virDomainSnapshotFindByName(vm->snapshots,
                                                snap->def->parent);
            snap->parent = other;
            other->nchildren++;
            snap->sibling = other->first_child;
            other->first_child = snap;
        }
6399
        virDomainObjEndAPI(&vm);
6400
    }
6401
    virObjectEventStateQueue(privconn->eventState, event);
6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413
    virDomainSnapshotDefFree(def);
    return snapshot;
}


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

6414
static int
6415
testDomainSnapshotDiscardAll(void *payload,
6416 6417
                             const void *name ATTRIBUTE_UNUSED,
                             void *data)
6418 6419 6420 6421 6422 6423 6424
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapRemoveDataPtr curr = data;

    if (snap->def->current)
        curr->current = true;
    virDomainSnapshotObjListRemove(curr->vm->snapshots, snap);
6425
    return 0;
6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436
}

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

6437
static int
6438 6439 6440 6441 6442 6443 6444
testDomainSnapshotReparentChildren(void *payload,
                                   const void *name ATTRIBUTE_UNUSED,
                                   void *data)
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapReparentDataPtr rep = data;

6445
    if (rep->err < 0)
6446
        return 0;
6447 6448 6449 6450 6451 6452 6453

    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;
6454
        return 0;
6455 6456 6457 6458
    }

    if (!snap->sibling)
        rep->last = snap;
6459
    return 0;
6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488
}

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) {
6489
            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)
6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532
                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;
6533
 cleanup:
6534
    virDomainObjEndAPI(&vm);
6535 6536 6537 6538 6539 6540 6541
    return ret;
}

static int
testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                           unsigned int flags)
{
6542
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6543 6544
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
6545 6546
    virObjectEventPtr event = NULL;
    virObjectEventPtr event2 = NULL;
6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609
    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;
6610 6611
    config = virDomainDefCopy(snap->def->dom, privconn->caps,
                              privconn->xmlopt, NULL, true);
6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623
    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.  */
6624 6625
            if (!virDomainDefCheckABIStability(vm->def, config,
                                               privconn->xmlopt)) {
6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638
                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);
6639
                event = virDomainEventLifecycleNewFromObj(vm,
6640 6641
                            VIR_DOMAIN_EVENT_STOPPED,
                            VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
6642
                virObjectEventStateQueue(privconn->eventState, event);
6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653
                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. */
6654
                event = virDomainEventLifecycleNewFromObj(vm,
6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667
                                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;
6668
            event = virDomainEventLifecycleNewFromObj(vm,
6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681
                                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 */
6682
                event2 = virDomainEventLifecycleNewFromObj(vm,
6683 6684 6685 6686 6687
                                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 已提交
6688
            virObjectUnref(event);
6689 6690 6691 6692
            event = NULL;

            if (was_stopped) {
                /* Transition 2 */
6693
                event = virDomainEventLifecycleNewFromObj(vm,
6694 6695 6696 6697
                                VIR_DOMAIN_EVENT_STARTED,
                                VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            } else if (was_running) {
                /* Transition 8 */
6698
                event = virDomainEventLifecycleNewFromObj(vm,
6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710
                                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);
6711
            event = virDomainEventLifecycleNewFromObj(vm,
6712 6713 6714 6715 6716 6717 6718 6719 6720
                                    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;

6721
            virObjectEventStateQueue(privconn->eventState, event);
6722
            event = virDomainEventLifecycleNewFromObj(vm,
6723 6724 6725
                            VIR_DOMAIN_EVENT_STARTED,
                            VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            if (paused) {
6726
                event2 = virDomainEventLifecycleNewFromObj(vm,
6727 6728 6729 6730 6731 6732 6733 6734
                                VIR_DOMAIN_EVENT_SUSPENDED,
                                VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
            }
        }
    }

    vm->current_snapshot = snap;
    ret = 0;
6735
 cleanup:
6736
    if (event) {
6737 6738
        virObjectEventStateQueue(privconn->eventState, event);
        virObjectEventStateQueue(privconn->eventState, event2);
C
Cole Robinson 已提交
6739
    } else {
C
Cédric Bosdonnat 已提交
6740
        virObjectUnref(event2);
6741
    }
6742
    virDomainObjEndAPI(&vm);
6743 6744 6745 6746 6747

    return ret;
}


6748
static virHypervisorDriver testHypervisorDriver = {
6749
    .name = "Test",
6750 6751 6752
    .connectOpen = testConnectOpen, /* 0.1.1 */
    .connectClose = testConnectClose, /* 0.1.1 */
    .connectGetVersion = testConnectGetVersion, /* 0.1.1 */
6753
    .connectGetHostname = testConnectGetHostname, /* 0.6.3 */
6754
    .connectGetMaxVcpus = testConnectGetMaxVcpus, /* 0.3.2 */
6755
    .nodeGetInfo = testNodeGetInfo, /* 0.1.1 */
6756
    .nodeGetCPUStats = testNodeGetCPUStats, /* 2.3.0 */
6757
    .nodeGetFreeMemory = testNodeGetFreeMemory, /* 2.3.0 */
6758
    .nodeGetFreePages = testNodeGetFreePages, /* 2.3.0 */
6759
    .connectGetCapabilities = testConnectGetCapabilities, /* 0.2.1 */
6760
    .connectGetSysinfo = testConnectGetSysinfo, /* 2.3.0 */
6761
    .connectGetType = testConnectGetType, /* 2.3.0 */
6762 6763 6764
    .connectListDomains = testConnectListDomains, /* 0.1.1 */
    .connectNumOfDomains = testConnectNumOfDomains, /* 0.1.1 */
    .connectListAllDomains = testConnectListAllDomains, /* 0.9.13 */
6765
    .domainCreateXML = testDomainCreateXML, /* 0.1.4 */
6766 6767 6768 6769 6770 6771 6772 6773 6774
    .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 */
6775
    .domainDestroyFlags = testDomainDestroyFlags, /* 4.2.0 */
6776 6777 6778 6779 6780
    .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 */
6781 6782
    .domainGetState = testDomainGetState, /* 0.9.2 */
    .domainSave = testDomainSave, /* 0.3.2 */
6783
    .domainSaveFlags = testDomainSaveFlags, /* 0.9.4 */
6784
    .domainRestore = testDomainRestore, /* 0.3.2 */
6785
    .domainRestoreFlags = testDomainRestoreFlags, /* 0.9.4 */
6786
    .domainCoreDump = testDomainCoreDump, /* 0.3.2 */
6787
    .domainCoreDumpWithFormat = testDomainCoreDumpWithFormat, /* 1.2.3 */
6788
    .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */
6789 6790 6791 6792
    .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */
    .domainGetVcpusFlags = testDomainGetVcpusFlags, /* 0.8.5 */
    .domainPinVcpu = testDomainPinVcpu, /* 0.7.3 */
    .domainGetVcpus = testDomainGetVcpus, /* 0.7.3 */
6793
    .domainGetVcpuPinInfo = testDomainGetVcpuPinInfo, /* 1.2.18 */
6794 6795
    .domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
    .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
6796 6797
    .connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
    .connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
6798 6799 6800
    .domainCreate = testDomainCreate, /* 0.1.11 */
    .domainCreateWithFlags = testDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = testDomainDefineXML, /* 0.1.11 */
6801
    .domainDefineXMLFlags = testDomainDefineXMLFlags, /* 1.2.12 */
6802
    .domainUndefine = testDomainUndefine, /* 0.1.11 */
6803
    .domainUndefineFlags = testDomainUndefineFlags, /* 0.9.4 */
6804 6805 6806
    .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
    .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
    .domainGetSchedulerType = testDomainGetSchedulerType, /* 0.3.2 */
6807 6808 6809 6810
    .domainGetSchedulerParameters = testDomainGetSchedulerParameters, /* 0.3.2 */
    .domainGetSchedulerParametersFlags = testDomainGetSchedulerParametersFlags, /* 0.9.2 */
    .domainSetSchedulerParameters = testDomainSetSchedulerParameters, /* 0.3.2 */
    .domainSetSchedulerParametersFlags = testDomainSetSchedulerParametersFlags, /* 0.9.2 */
6811 6812 6813
    .domainBlockStats = testDomainBlockStats, /* 0.7.0 */
    .domainInterfaceStats = testDomainInterfaceStats, /* 0.7.0 */
    .nodeGetCellsFreeMemory = testNodeGetCellsFreeMemory, /* 0.4.2 */
6814 6815 6816 6817
    .connectDomainEventRegister = testConnectDomainEventRegister, /* 0.6.0 */
    .connectDomainEventDeregister = testConnectDomainEventDeregister, /* 0.6.0 */
    .connectIsEncrypted = testConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = testConnectIsSecure, /* 0.7.3 */
6818 6819 6820
    .domainIsActive = testDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = testDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = testDomainIsUpdated, /* 0.8.6 */
6821 6822 6823
    .connectDomainEventRegisterAny = testConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = testConnectDomainEventDeregisterAny, /* 0.8.0 */
    .connectIsAlive = testConnectIsAlive, /* 0.9.8 */
6824
    .nodeGetCPUMap = testNodeGetCPUMap, /* 1.0.0 */
6825
    .domainRename = testDomainRename, /* 4.1.0 */
6826
    .domainScreenshot = testDomainScreenshot, /* 1.0.5 */
6827 6828
    .domainGetMetadata = testDomainGetMetadata, /* 1.1.3 */
    .domainSetMetadata = testDomainSetMetadata, /* 1.1.3 */
6829
    .connectGetCPUModelNames = testConnectGetCPUModelNames, /* 1.1.3 */
6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846
    .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 */
6847 6848 6849
    .domainSnapshotCreateXML = testDomainSnapshotCreateXML, /* 1.1.4 */
    .domainRevertToSnapshot = testDomainRevertToSnapshot, /* 1.1.4 */
    .domainSnapshotDelete = testDomainSnapshotDelete, /* 1.1.4 */
6850

E
Eric Blake 已提交
6851
    .connectBaselineCPU = testConnectBaselineCPU, /* 1.2.0 */
6852 6853 6854
};

static virNetworkDriver testNetworkDriver = {
6855 6856 6857 6858 6859
    .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 */
6860 6861
    .connectNetworkEventRegisterAny = testConnectNetworkEventRegisterAny, /* 1.2.1 */
    .connectNetworkEventDeregisterAny = testConnectNetworkEventDeregisterAny, /* 1.2.1 */
6862 6863 6864 6865
    .networkLookupByUUID = testNetworkLookupByUUID, /* 0.3.2 */
    .networkLookupByName = testNetworkLookupByName, /* 0.3.2 */
    .networkCreateXML = testNetworkCreateXML, /* 0.3.2 */
    .networkDefineXML = testNetworkDefineXML, /* 0.3.2 */
6866
    .networkUndefine = testNetworkUndefine, /* 0.3.2 */
6867
    .networkUpdate = testNetworkUpdate, /* 0.10.2 */
6868
    .networkCreate = testNetworkCreate, /* 0.3.2 */
6869 6870 6871 6872 6873 6874 6875
    .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 */
6876 6877
};

L
Laine Stump 已提交
6878
static virInterfaceDriver testInterfaceDriver = {
6879 6880 6881 6882
    .connectNumOfInterfaces = testConnectNumOfInterfaces, /* 0.7.0 */
    .connectListInterfaces = testConnectListInterfaces, /* 0.7.0 */
    .connectNumOfDefinedInterfaces = testConnectNumOfDefinedInterfaces, /* 0.7.0 */
    .connectListDefinedInterfaces = testConnectListDefinedInterfaces, /* 0.7.0 */
6883
    .connectListAllInterfaces = testConnectListAllInterfaces, /* 4.6.0 */
6884 6885
    .interfaceLookupByName = testInterfaceLookupByName, /* 0.7.0 */
    .interfaceLookupByMACString = testInterfaceLookupByMACString, /* 0.7.0 */
6886 6887 6888 6889 6890 6891
    .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 */
6892 6893 6894
    .interfaceChangeBegin = testInterfaceChangeBegin,   /* 0.9.2 */
    .interfaceChangeCommit = testInterfaceChangeCommit,  /* 0.9.2 */
    .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */
L
Laine Stump 已提交
6895 6896 6897
};


6898
static virStorageDriver testStorageDriver = {
6899 6900 6901 6902 6903 6904
    .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 */
6905 6906
    .connectStoragePoolEventRegisterAny = testConnectStoragePoolEventRegisterAny, /* 2.0.0 */
    .connectStoragePoolEventDeregisterAny = testConnectStoragePoolEventDeregisterAny, /* 2.0.0 */
6907 6908 6909
    .storagePoolLookupByName = testStoragePoolLookupByName, /* 0.5.0 */
    .storagePoolLookupByUUID = testStoragePoolLookupByUUID, /* 0.5.0 */
    .storagePoolLookupByVolume = testStoragePoolLookupByVolume, /* 0.5.0 */
6910 6911
    .storagePoolCreateXML = testStoragePoolCreateXML, /* 0.5.0 */
    .storagePoolDefineXML = testStoragePoolDefineXML, /* 0.5.0 */
6912 6913
    .storagePoolBuild = testStoragePoolBuild, /* 0.5.0 */
    .storagePoolUndefine = testStoragePoolUndefine, /* 0.5.0 */
6914
    .storagePoolCreate = testStoragePoolCreate, /* 0.5.0 */
6915 6916 6917 6918 6919 6920 6921
    .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 */
6922
    .storagePoolNumOfVolumes = testStoragePoolNumOfVolumes, /* 0.5.0 */
6923 6924 6925
    .storagePoolListVolumes = testStoragePoolListVolumes, /* 0.5.0 */
    .storagePoolListAllVolumes = testStoragePoolListAllVolumes, /* 0.10.2 */

6926 6927 6928 6929 6930 6931 6932 6933 6934
    .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 */
6935 6936
    .storagePoolIsActive = testStoragePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = testStoragePoolIsPersistent, /* 0.7.3 */
6937 6938
};

6939
static virNodeDeviceDriver testNodeDeviceDriver = {
6940
    .connectListAllNodeDevices = testConnectListAllNodeDevices, /* 4.1.0 */
6941 6942
    .connectNodeDeviceEventRegisterAny = testConnectNodeDeviceEventRegisterAny, /* 2.2.0 */
    .connectNodeDeviceEventDeregisterAny = testConnectNodeDeviceEventDeregisterAny, /* 2.2.0 */
6943 6944 6945 6946 6947 6948 6949 6950 6951
    .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 */
6952 6953
};

6954
static virConnectDriver testConnectDriver = {
6955
    .localOnly = true,
6956
    .uriSchemes = (const char *[]){ "test", NULL },
6957 6958 6959 6960 6961 6962 6963
    .hypervisorDriver = &testHypervisorDriver,
    .interfaceDriver = &testInterfaceDriver,
    .networkDriver = &testNetworkDriver,
    .nodeDeviceDriver = &testNodeDeviceDriver,
    .nwfilterDriver = NULL,
    .secretDriver = NULL,
    .storageDriver = &testStorageDriver,
6964 6965
};

6966 6967 6968 6969 6970 6971 6972 6973
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
6974 6975
    return virRegisterConnectDriver(&testConnectDriver,
                                    false);
6976
}