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

24
#include <config.h>
25

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

35

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

71 72
#define VIR_FROM_THIS VIR_FROM_TEST

73 74
VIR_LOG_INIT("test.test_driver");

75

76 77 78 79
#define MAX_CPUS 128

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

#define MAX_CELLS 128
88

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

96
struct _testDriver {
97
    virMutex lock;
98

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

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

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

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

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

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

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

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

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

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

    VIR_FREE(driver);
}
165

166

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

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

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

    virObjectEventStateQueue(driver->eventState, event);
}

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

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

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

static void
testDomainDefNamespaceFree(void *data)
{
    testDomainNamespaceDefPtr nsdata = data;
203 204 205 206 207 208 209 210 211
    size_t i;

    if (!nsdata)
        return;

    for (i = 0; i < nsdata->num_snap_nodes; i++)
        xmlFreeNode(nsdata->snap_nodes[i]);

    VIR_FREE(nsdata->snap_nodes);
212 213 214 215 216 217 218 219 220 221
    VIR_FREE(nsdata);
}

static int
testDomainDefNamespaceParse(xmlDocPtr xml ATTRIBUTE_UNUSED,
                            xmlNodePtr root ATTRIBUTE_UNUSED,
                            xmlXPathContextPtr ctxt,
                            void **data)
{
    testDomainNamespaceDefPtr nsdata = NULL;
222 223 224
    xmlNodePtr *nodes = NULL;
    int tmp, n;
    size_t i;
225 226 227 228 229 230 231 232 233 234 235 236 237
    unsigned int tmpuint;

    if (xmlXPathRegisterNs(ctxt, BAD_CAST "test",
                           BAD_CAST TEST_NAMESPACE_HREF) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to register xml namespace '%s'"),
                       TEST_NAMESPACE_HREF);
        return -1;
    }

    if (VIR_ALLOC(nsdata) < 0)
        return -1;

238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
    n = virXPathNodeSet("./test:domainsnapshot", ctxt, &nodes);
    if (n < 0)
        goto error;

    if (n && VIR_ALLOC_N(nsdata->snap_nodes, n) < 0)
        goto error;

    for (i = 0; i < n; i++) {
        xmlNodePtr newnode = xmlCopyNode(nodes[i], 1);
        if (!newnode) {
            virReportOOMError();
            goto error;
        }

        nsdata->snap_nodes[nsdata->num_snap_nodes] = newnode;
        nsdata->num_snap_nodes++;
    }
    VIR_FREE(nodes);

257 258 259 260 261 262 263
    tmp = virXPathBoolean("boolean(./test:transient)", ctxt);
    if (tmp == -1) {
        virReportError(VIR_ERR_XML_ERROR, "%s", _("invalid transient"));
        goto error;
    }
    nsdata->transient = tmp;

C
Cole Robinson 已提交
264 265 266 267 268 269 270
    tmp = virXPathBoolean("boolean(./test:hasmanagedsave)", ctxt);
    if (tmp == -1) {
        virReportError(VIR_ERR_XML_ERROR, "%s", _("invalid hasmanagedsave"));
        goto error;
    }
    nsdata->hasManagedSave = tmp;

271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
    tmp = virXPathUInt("string(./test:runstate)", ctxt, &tmpuint);
    if (tmp == 0) {
        if (tmpuint >= VIR_DOMAIN_LAST) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("runstate '%d' out of range'"), tmpuint);
            goto error;
        }
        nsdata->runstate = tmpuint;
    } else if (tmp == -1) {
        nsdata->runstate = VIR_DOMAIN_RUNNING;
    } else if (tmp == -2) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid runstate"));
        goto error;
    }

287 288 289 290 291
    if (nsdata->transient && nsdata->runstate == VIR_DOMAIN_SHUTOFF) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
            _("transient domain cannot have runstate 'shutoff'"));
        goto error;
    }
C
Cole Robinson 已提交
292 293 294 295 296
    if (nsdata->hasManagedSave && nsdata->runstate != VIR_DOMAIN_SHUTOFF) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
            _("domain with managedsave data can only have runstate 'shutoff'"));
        goto error;
    }
297

298 299 300
    *data = nsdata;
    return 0;

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

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

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

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

325 326 327 328 329 330
    if (VIR_ALLOC_N(caps->host.pagesSize, 2) < 0)
        goto error;

    caps->host.pagesSize[caps->host.nPagesSize++] = 4;
    caps->host.pagesSize[caps->host.nPagesSize++] = 2048;

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

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

        nPages = caps->host.nPagesSize;
343 344 345 346

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

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

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

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

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

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

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

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

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

391
    return caps;
392

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

398

399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
static testDriverPtr
testDriverNew(void)
{
    virDomainXMLNamespace ns = {
        .parse = testDomainDefNamespaceParse,
        .free = testDomainDefNamespaceFree,
    };
    testDriverPtr ret;

    if (VIR_ALLOC(ret) < 0)
        return NULL;

    if (virMutexInit(&ret->lock) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot initialize mutex"));
        goto error;
    }

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

426
    virAtomicIntSet(&ret->nextDomID, 1);
427 428 429 430 431 432 433 434 435

    return ret;

 error:
    testDriverFree(ret);
    return NULL;
}


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

C
Cole Robinson 已提交
544

545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
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";

568
static const unsigned long long defaultPoolCap = (100 * 1024 * 1024 * 1024ull);
569
static const unsigned long long defaultPoolAlloc;
C
Cole Robinson 已提交
570

571
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr obj);
572
static int testNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
573

574 575 576 577
static virDomainObjPtr
testDomObjFromDomain(virDomainPtr domain)
{
    virDomainObjPtr vm;
578
    testDriverPtr driver = domain->conn->privateData;
579 580
    char uuidstr[VIR_UUID_STRING_BUFLEN];

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

    return vm;
}

592
static char *
593 594
testDomainGenerateIfname(virDomainDefPtr domdef)
{
595
    int maxif = 1024;
596
    int ifctr;
597 598

    for (ifctr = 0; ifctr < maxif; ++ifctr) {
M
Michal Privoznik 已提交
599
        virDomainNetDefPtr net = NULL;
600 601
        char *ifname;

602
        if (virAsprintf(&ifname, "testnet%d", ifctr) < 0)
603 604 605
            return NULL;

        /* Generate network interface names */
M
Michal Privoznik 已提交
606
        if (!(net = virDomainNetFindByName(domdef, ifname)))
607
            return ifname;
608
        VIR_FREE(ifname);
609 610
    }

611 612
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Exceeded max iface limit %d"), maxif);
613 614 615
    return NULL;
}

616
static int
617
testDomainGenerateIfnames(virDomainDefPtr domdef)
618
{
619
    size_t i = 0;
620 621 622 623 624 625

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

626
        ifname = testDomainGenerateIfname(domdef);
627
        if (!ifname)
628
            return -1;
629 630 631 632

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

633
    return 0;
634 635
}

636

637 638
static void
testDomainShutdownState(virDomainPtr domain,
J
Jiri Denemark 已提交
639 640
                        virDomainObjPtr privdom,
                        virDomainShutoffReason reason)
641
{
642
    virDomainObjRemoveTransientDef(privdom);
J
Jiri Denemark 已提交
643
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF, reason);
644

645 646 647 648
    if (domain)
        domain->id = -1;
}

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

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

660
    if (virDomainObjSetDefTransient(privconn->caps,
661
                                    privconn->xmlopt,
662
                                    dom) < 0) {
663 664 665
        goto cleanup;
    }

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

674

675
static char *testBuildFilename(const char *relativeTo,
676 677
                               const char *filename)
{
678 679
    char *offset;
    int baseLen;
680 681
    char *ret;

682
    if (!filename || filename[0] == '\0')
683
        return NULL;
684 685 686 687
    if (filename[0] == '/') {
        ignore_value(VIR_STRDUP(ret, filename));
        return ret;
    }
688

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

C
Cole Robinson 已提交
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737
static xmlNodePtr
testParseXMLDocFromFile(xmlNodePtr node, const char *file, const char *type)
{
    xmlNodePtr ret = NULL;
    xmlDocPtr doc = NULL;
    char *absFile = NULL;
    char *relFile = virXMLPropString(node, "file");

    if (relFile != NULL) {
        absFile = testBuildFilename(file, relFile);
        VIR_FREE(relFile);
        if (!absFile) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("resolving %s filename"), type);
            return NULL;
        }

        if (!(doc = virXMLParse(absFile, NULL, type)))
            goto error;

        ret = xmlCopyNode(xmlDocGetRootElement(doc), 1);
        if (!ret) {
            virReportOOMError();
            goto error;
        }
        xmlReplaceNode(node, ret);
        xmlFreeNode(node);
    } else {
        ret = node;
    }

738
 error:
C
Cole Robinson 已提交
739 740 741 742 743
    xmlFreeDoc(doc);
    VIR_FREE(absFile);
    return ret;
}

744 745 746
static int
testParseNodeInfo(virNodeInfoPtr nodeInfo, xmlXPathContextPtr ctxt)
{
747
    char *str;
748 749
    long l;
    int ret;
750

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

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

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

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

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

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

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

827
    return 0;
828
 error:
829 830 831
    return -1;
}

832
static int
833
testParseDomainSnapshots(testDriverPtr privconn,
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 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883
                         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;
884
 error:
885 886 887
    return ret;
}

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

    num = virXPathNodeSet("/node/domain", ctxt, &nodes);
899
    if (num < 0)
900 901
        goto error;

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

        def = virDomainDefParseNode(ctxt->doc, node,
910
                                    privconn->caps, privconn->xmlopt, NULL,
911
                                    VIR_DOMAIN_DEF_PARSE_INACTIVE);
C
Cole Robinson 已提交
912 913
        if (!def)
            goto error;
914

915
        if (testDomainGenerateIfnames(def) < 0 ||
916
            !(obj = virDomainObjListAdd(privconn->domains,
917
                                        def,
918
                                        privconn->xmlopt,
919
                                        0, NULL))) {
920
            virDomainDefFree(def);
921 922
            goto error;
        }
923

924 925 926 927 928
        if (testParseDomainSnapshots(privconn, obj, file, ctxt) < 0) {
            virObjectUnlock(obj);
            goto error;
        }

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

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

944
        virObjectUnlock(obj);
945
    }
946

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

953

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

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

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

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

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

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

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

993

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

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

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

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

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

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

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

1034

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

    /* Find storage volumes */
1049
    if (virAsprintf(&vol_xpath, "/node/pool[%d]/volume", objidx) < 0)
1050 1051 1052 1053
        goto error;

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

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

1063
        if (!(volDef = virStorageVolDefParseNode(def, ctxt->doc, node, 0)))
C
Cole Robinson 已提交
1064
            goto error;
1065

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

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

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

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

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

1090

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

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

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

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

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

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

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

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

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

1142

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

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

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

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

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

1173
        virNodeDeviceObjEndAPI(&obj);
1174 1175 1176
    }

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

1182
static int
1183
testParseAuthUsers(testDriverPtr privconn,
1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216
                   xmlXPathContextPtr ctxt)
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;

    num = virXPathNodeSet("/node/auth/user", ctxt, &nodes);
    if (num < 0)
        goto error;

    privconn->numAuths = num;
    if (num && VIR_ALLOC_N(privconn->auths, num) < 0)
        goto error;

    for (i = 0; i < num; i++) {
        char *username, *password;

        ctxt->node = nodes[i];
        username = virXPathString("string(.)", ctxt);
        if (!username || STREQ(username, "")) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("missing username in /node/auth/user field"));
            VIR_FREE(username);
            goto error;
        }
        /* This field is optional. */
        password = virXMLPropString(nodes[i], "password");

        privconn->auths[i].username = username;
        privconn->auths[i].password = password;
    }

    ret = 0;
1217
 error:
1218 1219 1220
    VIR_FREE(nodes);
    return ret;
}
1221

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

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

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

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

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

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

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

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

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

1284
    return 0;
1285 1286

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

1294 1295 1296 1297 1298 1299 1300
/* Simultaneous test:///default connections should share the same
 * common state (among other things, this allows testing event
 * detection in one connection for an action caused in another).  */
static int
testOpenDefault(virConnectPtr conn)
{
    testDriverPtr privconn = NULL;
1301 1302
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
1303
    size_t i;
1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320

    virMutexLock(&defaultLock);
    if (defaultConnections++) {
        conn->privateData = defaultConn;
        virMutexUnlock(&defaultLock);
        return VIR_DRV_OPEN_SUCCESS;
    }

    if (!(privconn = testDriverNew()))
        goto error;

    conn->privateData = privconn;

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

    /* Numa setup */
    privconn->numCells = 2;
1321 1322 1323 1324
    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;
1325
    }
1326
    for (i = 0; i < 16; i++) {
1327 1328 1329
        virBitmapPtr siblings = virBitmapNew(16);
        if (!siblings)
            goto error;
1330 1331 1332 1333 1334
        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;
1335 1336 1337 1338 1339
    }

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

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

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

    defaultConn = privconn;

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

    return VIR_DRV_OPEN_SUCCESS;

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

1365 1366 1367 1368
static int
testConnectAuthenticate(virConnectPtr conn,
                        virConnectAuthPtr auth)
{
1369
    testDriverPtr privconn = conn->privateData;
1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393
    int ret = -1;
    ssize_t i;
    char *username = NULL, *password = NULL;

    if (privconn->numAuths == 0)
        return 0;

    /* Authentication is required because the test XML contains a
     * non-empty <auth/> section.  First we must ask for a username.
     */
    username = virAuthGetUsername(conn, auth, "test", NULL, "localhost"/*?*/);
    if (!username) {
        virReportError(VIR_ERR_AUTH_FAILED, "%s",
                       _("authentication failed when asking for username"));
        goto cleanup;
    }

    /* Does the username exist? */
    for (i = 0; i < privconn->numAuths; ++i) {
        if (STREQ(privconn->auths[i].username, username))
            goto found_user;
    }
    i = -1;

1394
 found_user:
1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413
    /* Even if we didn't find the user, we still ask for a password. */
    if (i == -1 || privconn->auths[i].password != NULL) {
        password = virAuthGetPassword(conn, auth, "test",
                                      username, "localhost");
        if (password == NULL) {
            virReportError(VIR_ERR_AUTH_FAILED, "%s",
                           _("authentication failed when asking for password"));
            goto cleanup;
        }
    }

    if (i == -1 ||
        (password && STRNEQ(privconn->auths[i].password, password))) {
        virReportError(VIR_ERR_AUTH_FAILED, "%s",
                       _("authentication failed, see test XML for the correct username/password"));
        goto cleanup;
    }

    ret = 0;
1414
 cleanup:
1415 1416 1417 1418
    VIR_FREE(username);
    VIR_FREE(password);
    return ret;
}
1419

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

E
Eric Blake 已提交
1427 1428
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

1429
    if (!conn->uri)
1430
        return VIR_DRV_OPEN_DECLINED;
1431

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

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

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

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

1454 1455 1456
    if (ret != VIR_DRV_OPEN_SUCCESS)
        return ret;

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

1461
    return VIR_DRV_OPEN_SUCCESS;
1462 1463
}

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

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

1478
    testDriverLock(privconn);
1479
    testDriverFree(privconn);
1480 1481 1482

    if (dflt) {
        defaultConn = NULL;
1483
        virMutexUnlock(&defaultLock);
1484 1485
    }

1486
    conn->privateData = NULL;
1487
    return 0;
1488 1489
}

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

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


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

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

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

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

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

    virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, NULL);

J
Jiri Denemark 已提交
1536 1537 1538
    if (!(cpus = virCPUDefListParse(xmlCPUs, ncpus, VIR_CPU_TYPE_HOST)))
        goto cleanup;

1539
    if (!(cpu = cpuBaseline(cpus, ncpus, NULL, false)))
J
Jiri Denemark 已提交
1540 1541 1542 1543 1544 1545
        goto cleanup;

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

1546
    cpustr = virCPUDefFormat(cpu, NULL);
J
Jiri Denemark 已提交
1547 1548 1549 1550

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

J
Jiri Denemark 已提交
1552
    return cpustr;
1553 1554
}

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

1565
static char *testConnectGetCapabilities(virConnectPtr conn)
1566
{
1567
    testDriverPtr privconn = conn->privateData;
1568
    char *xml;
1569
    testDriverLock(privconn);
1570
    xml = virCapabilitiesFormatXML(privconn->caps);
1571
    testDriverUnlock(privconn);
1572
    return xml;
1573 1574
}

1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594
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;
}

1595 1596 1597 1598 1599 1600
static const char *
testConnectGetType(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return "TEST";
}

1601
static int testConnectNumOfDomains(virConnectPtr conn)
1602
{
1603
    testDriverPtr privconn = conn->privateData;
1604
    int count;
1605

1606
    testDriverLock(privconn);
1607
    count = virDomainObjListNumOfDomains(privconn->domains, true, NULL, NULL);
1608
    testDriverUnlock(privconn);
1609

1610
    return count;
1611 1612
}

1613 1614 1615
static int testDomainIsActive(virDomainPtr dom)
{
    virDomainObjPtr obj;
1616
    int ret;
1617

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

1621 1622
    ret = virDomainObjIsActive(obj);
    virDomainObjEndAPI(&obj);
1623 1624 1625 1626 1627 1628
    return ret;
}

static int testDomainIsPersistent(virDomainPtr dom)
{
    virDomainObjPtr obj;
1629 1630 1631 1632
    int ret;

    if (!(obj = testDomObjFromDomain(dom)))
        return -1;
1633 1634 1635

    ret = obj->persistent;

1636
    virDomainObjEndAPI(&obj);
1637 1638 1639
    return ret;
}

1640 1641 1642 1643 1644
static int testDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
{
    return 0;
}

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

1656 1657 1658
    virCheckFlags(VIR_DOMAIN_START_VALIDATE, NULL);

    if (flags & VIR_DOMAIN_START_VALIDATE)
1659
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
1660

1661
    testDriverLock(privconn);
1662
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
1663
                                       NULL, parse_flags)) == NULL)
1664
        goto cleanup;
1665

1666
    if (testDomainGenerateIfnames(def) < 0)
1667
        goto cleanup;
1668
    if (!(dom = virDomainObjListAdd(privconn->domains,
1669
                                    def,
1670
                                    privconn->xmlopt,
1671
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
1672 1673
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
1674 1675
        goto cleanup;
    def = NULL;
1676

1677 1678 1679 1680 1681
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_BOOTED) < 0) {
        if (!dom->persistent) {
            virDomainObjListRemove(privconn->domains, dom);
            dom = NULL;
        }
1682
        goto cleanup;
1683
    }
1684

1685
    event = virDomainEventLifecycleNewFromObj(dom,
1686 1687 1688
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);

1689
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
1690

1691
 cleanup:
1692
    if (dom)
1693
        virObjectUnlock(dom);
1694
    testObjectEventQueue(privconn, event);
1695
    virDomainDefFree(def);
1696
    testDriverUnlock(privconn);
1697
    return ret;
1698 1699 1700
}


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

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

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

1715
 cleanup:
1716
    if (dom)
1717
        virObjectUnlock(dom);
1718
    return ret;
1719 1720
}

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

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

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

1735
 cleanup:
1736
    if (dom)
1737
        virObjectUnlock(dom);
1738
    return ret;
1739 1740
}

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

1748
    if (!(dom = virDomainObjListFindByName(privconn->domains, name))) {
1749
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1750
        goto cleanup;
1751
    }
1752

1753
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
1754

1755
 cleanup:
1756
    virDomainObjEndAPI(&dom);
1757
    return ret;
1758 1759
}

1760 1761 1762
static int testConnectListDomains(virConnectPtr conn,
                                  int *ids,
                                  int maxids)
1763
{
1764
    testDriverPtr privconn = conn->privateData;
1765

1766 1767
    return virDomainObjListGetActiveIDs(privconn->domains, ids, maxids,
                                        NULL, NULL);
1768 1769
}

1770
static int testDomainDestroy(virDomainPtr domain)
1771
{
1772
    testDriverPtr privconn = domain->conn->privateData;
1773
    virDomainObjPtr privdom;
1774
    virObjectEventPtr event = NULL;
1775
    int ret = -1;
1776

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

1780 1781 1782 1783 1784 1785
    if (!virDomainObjIsActive(privdom)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto cleanup;
    }

J
Jiri Denemark 已提交
1786
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_DESTROYED);
1787
    event = virDomainEventLifecycleNewFromObj(privdom,
1788 1789
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
1790

1791 1792
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
1793 1794

    ret = 0;
1795
 cleanup:
1796
    virDomainObjEndAPI(&privdom);
1797
    testObjectEventQueue(privconn, event);
1798
    return ret;
1799 1800
}

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

1808 1809
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1810

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

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

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

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

1838 1839
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1840

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

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

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

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

1868 1869
    virCheckFlags(0, -1);

1870

1871
    if (!(privdom = testDomObjFromDomain(domain)))
1872
        goto cleanup;
1873

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

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

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

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

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

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


1910
    if (!(privdom = testDomObjFromDomain(domain)))
1911
        goto cleanup;
1912

1913 1914 1915 1916 1917 1918
    if (!virDomainObjIsActive(privdom)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto cleanup;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    virCheckFlags(0, -1);

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

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

2009
    virDomainObjEndAPI(&privdom);
2010 2011

    return 0;
2012 2013
}

2014 2015
#define TEST_SAVE_MAGIC "TestGuestMagic"

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

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

2035

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

2039 2040 2041 2042 2043 2044
    if (!virDomainObjIsActive(privdom)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto cleanup;
    }

2045
    xml = virDomainDefFormat(privdom->def, privconn->caps,
2046
                             VIR_DOMAIN_DEF_FORMAT_SECURE);
C
Cole Robinson 已提交
2047

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

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

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

J
Jiri Denemark 已提交
2089
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SAVED);
2090
    event = virDomainEventLifecycleNewFromObj(privdom,
2091 2092
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
2093

2094 2095
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
2096

2097
    ret = 0;
2098
 cleanup:
2099 2100 2101 2102
    VIR_FREE(xml);

    /* Don't report failure in close or unlink, because
     * in either case we're already in a failure scenario
Y
Yuri Chornoivan 已提交
2103
     * and have reported an earlier error */
2104
    if (ret != 0) {
2105
        VIR_FORCE_CLOSE(fd);
2106 2107
        unlink(path);
    }
2108
    virDomainObjEndAPI(&privdom);
2109
    testObjectEventQueue(privconn, event);
2110
    return ret;
2111 2112
}

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

2136 2137
    virCheckFlags(0, -1);
    if (dxml) {
2138 2139
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
2140 2141 2142
        return -1;
    }

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

2180
    def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
2181
                                  NULL, VIR_DOMAIN_DEF_PARSE_INACTIVE);
2182
    if (!def)
2183
        goto cleanup;
2184

2185
    if (testDomainGenerateIfnames(def) < 0)
2186
        goto cleanup;
2187
    if (!(dom = virDomainObjListAdd(privconn->domains,
2188
                                    def,
2189
                                    privconn->xmlopt,
2190 2191 2192
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
2193 2194
        goto cleanup;
    def = NULL;
2195

2196 2197 2198 2199 2200
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_RESTORED) < 0) {
        if (!dom->persistent) {
            virDomainObjListRemove(privconn->domains, dom);
            dom = NULL;
        }
2201
        goto cleanup;
2202
    }
2203

2204
    event = virDomainEventLifecycleNewFromObj(dom,
2205 2206
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
2207
    ret = 0;
2208

2209
 cleanup:
2210 2211
    virDomainDefFree(def);
    VIR_FREE(xml);
2212
    VIR_FORCE_CLOSE(fd);
2213
    if (dom)
2214
        virObjectUnlock(dom);
2215
    testObjectEventQueue(privconn, event);
2216
    return ret;
2217 2218
}

2219 2220 2221 2222 2223 2224 2225
static int
testDomainRestore(virConnectPtr conn,
                  const char *path)
{
    return testDomainRestoreFlags(conn, path, NULL, 0);
}

2226 2227 2228 2229
static int testDomainCoreDumpWithFormat(virDomainPtr domain,
                                        const char *to,
                                        unsigned int dumpformat,
                                        unsigned int flags)
2230
{
2231
    testDriverPtr privconn = domain->conn->privateData;
2232
    int fd = -1;
2233
    virDomainObjPtr privdom;
2234
    virObjectEventPtr event = NULL;
2235
    int ret = -1;
2236

E
Eric Blake 已提交
2237 2238
    virCheckFlags(VIR_DUMP_CRASH, -1);

2239

2240
    if (!(privdom = testDomObjFromDomain(domain)))
2241
        goto cleanup;
2242

2243 2244 2245 2246 2247 2248
    if (!virDomainObjIsActive(privdom)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto cleanup;
    }

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

2268 2269 2270 2271 2272 2273 2274
    /* 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;
    }

2275
    if (flags & VIR_DUMP_CRASH) {
J
Jiri Denemark 已提交
2276
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_CRASHED);
2277
        event = virDomainEventLifecycleNewFromObj(privdom,
2278 2279
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
2280 2281
        if (!privdom->persistent)
            virDomainObjListRemove(privconn->domains, privdom);
2282
    }
2283

2284
    ret = 0;
2285
 cleanup:
2286
    VIR_FORCE_CLOSE(fd);
2287
    virDomainObjEndAPI(&privdom);
2288
    testObjectEventQueue(privconn, event);
2289
    return ret;
2290 2291
}

2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305

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)
{
2306 2307 2308
    char *ret;

    ignore_value(VIR_STRDUP(ret, "linux"));
2309
    return ret;
2310 2311
}

2312 2313 2314

static unsigned long long
testDomainGetMaxMemory(virDomainPtr domain)
2315
{
2316
    virDomainObjPtr privdom;
2317
    unsigned long long ret = 0;
2318

2319 2320
    if (!(privdom = testDomObjFromDomain(domain)))
        return 0;
2321

2322
    ret = virDomainDefGetMemoryTotal(privdom->def);
2323

2324
    virDomainObjEndAPI(&privdom);
2325
    return ret;
2326 2327
}

2328 2329
static int testDomainSetMaxMemory(virDomainPtr domain,
                                  unsigned long memory)
2330
{
2331 2332
    virDomainObjPtr privdom;

2333 2334
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2335 2336

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

2339
    virDomainObjEndAPI(&privdom);
2340
    return 0;
2341 2342
}

2343 2344
static int testDomainSetMemory(virDomainPtr domain,
                               unsigned long memory)
2345
{
2346
    virDomainObjPtr privdom;
2347
    int ret = -1;
2348

2349 2350
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2351

2352
    if (memory > virDomainDefGetMemoryTotal(privdom->def)) {
2353
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2354
        goto cleanup;
2355
    }
2356

2357
    privdom->def->mem.cur_balloon = memory;
2358 2359
    ret = 0;

2360
 cleanup:
2361
    virDomainObjEndAPI(&privdom);
2362
    return ret;
2363 2364
}

2365 2366
static int
testDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
C
Cole Robinson 已提交
2367
{
2368 2369 2370 2371
    virDomainObjPtr vm;
    virDomainDefPtr def;
    int ret = -1;

2372 2373
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2374 2375
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

2376 2377
    if (!(vm = testDomObjFromDomain(domain)))
        return -1;
2378

2379
    if (!(def = virDomainObjGetOneDef(vm, flags)))
2380
        goto cleanup;
2381

2382 2383 2384
    if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
        ret = virDomainDefGetVcpusMax(def);
    else
2385
        ret = virDomainDefGetVcpus(def);
2386

2387
 cleanup:
2388
    virDomainObjEndAPI(&vm);
2389
    return ret;
C
Cole Robinson 已提交
2390 2391
}

2392 2393 2394
static int
testDomainGetMaxVcpus(virDomainPtr domain)
{
2395
    return testDomainGetVcpusFlags(domain, (VIR_DOMAIN_AFFECT_LIVE |
2396 2397 2398 2399 2400 2401 2402
                                            VIR_DOMAIN_VCPU_MAXIMUM));
}

static int
testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
                        unsigned int flags)
{
2403
    testDriverPtr driver = domain->conn->privateData;
2404
    virDomainObjPtr privdom = NULL;
2405
    virDomainDefPtr def;
2406
    virDomainDefPtr persistentDef;
C
Cole Robinson 已提交
2407 2408
    int ret = -1, maxvcpus;

2409 2410
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2411 2412
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

2413
    if ((maxvcpus = testConnectGetMaxVcpus(domain->conn, NULL)) < 0)
2414
        return -1;
2415 2416

    if (nrCpus > maxvcpus) {
2417
        virReportError(VIR_ERR_INVALID_ARG,
2418 2419
                       _("requested cpu amount exceeds maximum supported amount "
                         "(%d > %d)"), nrCpus, maxvcpus);
2420 2421
        return -1;
    }
2422

2423 2424
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2425

2426
    if (virDomainObjGetDefs(privdom, flags, &def, &persistentDef) < 0)
C
Cole Robinson 已提交
2427 2428
        goto cleanup;

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

2436 2437
    if (persistentDef &&
        !(flags & VIR_DOMAIN_VCPU_MAXIMUM) &&
2438
        virDomainDefGetVcpusMax(persistentDef) < nrCpus) {
2439 2440
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested cpu amount exceeds maximum (%d > %d)"),
2441
                       nrCpus, virDomainDefGetVcpusMax(persistentDef));
2442
        goto cleanup;
2443
    }
2444

2445 2446 2447
    if (def &&
        virDomainDefSetVcpus(def, nrCpus) < 0)
        goto cleanup;
2448

2449 2450
    if (persistentDef) {
        if (flags & VIR_DOMAIN_VCPU_MAXIMUM) {
2451 2452
            if (virDomainDefSetVcpusMax(persistentDef, nrCpus,
                                        driver->xmlopt) < 0)
2453
                goto cleanup;
2454
        } else {
2455 2456
            if (virDomainDefSetVcpus(persistentDef, nrCpus) < 0)
                goto cleanup;
2457
        }
2458
    }
2459

2460 2461
    ret = 0;

2462
 cleanup:
2463
    virDomainObjEndAPI(&privdom);
2464
    return ret;
2465 2466
}

2467
static int
2468
testDomainSetVcpus(virDomainPtr domain, unsigned int nrCpus)
2469
{
2470
    return testDomainSetVcpusFlags(domain, nrCpus, VIR_DOMAIN_AFFECT_LIVE);
2471 2472
}

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

2489 2490
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
C
Cole Robinson 已提交
2491 2492

    if (!virDomainObjIsActive(privdom)) {
2493
        virReportError(VIR_ERR_OPERATION_INVALID,
2494
                       "%s", _("cannot list vcpus for an inactive domain"));
C
Cole Robinson 已提交
2495 2496 2497
        goto cleanup;
    }

2498
    def = privdom->def;
C
Cole Robinson 已提交
2499 2500

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

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

    hostcpus = VIR_NODEINFO_MAXCPUS(privconn->nodeInfo);
2509 2510 2511 2512 2513
    if (!(allcpumap = virBitmapNew(hostcpus)))
        goto cleanup;

    virBitmapSetAll(allcpumap);

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

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

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

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

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

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

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

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

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

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

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

2566 2567
    def = privdom->def;

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

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

2582 2583 2584
    virBitmapFree(vcpuinfo->cpumask);

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

    ret = 0;
2588

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

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

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

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

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

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

2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704
static int
testDomainRenameCallback(virDomainObjPtr privdom,
                         const char *new_name,
                         unsigned int flags,
                         void *opaque)
{
    testDriverPtr driver = opaque;
    virObjectEventPtr event_new = NULL;
    virObjectEventPtr event_old = NULL;
    int ret = -1;
    char *new_dom_name = NULL;
    char *old_dom_name = NULL;

    virCheckFlags(0, -1);

    if (VIR_STRDUP(new_dom_name, new_name) < 0)
        goto cleanup;

    event_old = virDomainEventLifecycleNewFromObj(privdom,
                                                  VIR_DOMAIN_EVENT_UNDEFINED,
                                                  VIR_DOMAIN_EVENT_UNDEFINED_RENAMED);

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

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

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

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

    virCheckFlags(0, ret);

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

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

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

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

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

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

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

2705
static char *testDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
2706
{
2707
    testDriverPtr privconn = domain->conn->privateData;
2708
    virDomainDefPtr def;
2709
    virDomainObjPtr privdom;
2710 2711
    char *ret = NULL;

2712 2713
    /* Flags checked by virDomainDefFormat */

2714 2715
    if (!(privdom = testDomObjFromDomain(domain)))
        return NULL;
2716

2717 2718
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
2719

2720 2721
    ret = virDomainDefFormat(def, privconn->caps,
                             virDomainDefFormatConvertXMLFlags(flags));
2722

2723
    virDomainObjEndAPI(&privdom);
2724
    return ret;
2725
}
2726

2727 2728
static int testConnectNumOfDefinedDomains(virConnectPtr conn)
{
2729
    testDriverPtr privconn = conn->privateData;
2730

2731
    return virDomainObjListNumOfDomains(privconn->domains, false, NULL, NULL);
2732 2733
}

2734 2735
static int testConnectListDefinedDomains(virConnectPtr conn,
                                         char **const names,
2736 2737
                                         int maxnames)
{
2738

2739
    testDriverPtr privconn = conn->privateData;
2740 2741

    memset(names, 0, sizeof(*names)*maxnames);
2742 2743
    return virDomainObjListGetInactiveNames(privconn->domains, names, maxnames,
                                            NULL, NULL);
2744 2745
}

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

    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
2759

2760
    if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
2761
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
2762

2763
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
2764
                                       NULL, parse_flags)) == NULL)
2765
        goto cleanup;
2766

2767 2768 2769
    if (virXMLCheckIllegalChars("name", def->name, "\n") < 0)
        goto cleanup;

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

2781
    event = virDomainEventLifecycleNewFromObj(dom,
2782
                                     VIR_DOMAIN_EVENT_DEFINED,
2783
                                     !oldDef ?
2784 2785
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
2786

2787
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
2788

2789
 cleanup:
2790
    virDomainDefFree(def);
2791
    virDomainDefFree(oldDef);
2792
    if (dom)
2793
        virObjectUnlock(dom);
2794
    testObjectEventQueue(privconn, event);
2795
    return ret;
2796 2797
}

2798 2799 2800 2801 2802 2803
static virDomainPtr
testDomainDefineXML(virConnectPtr conn, const char *xml)
{
    return testDomainDefineXMLFlags(conn, xml, 0);
}

2804 2805 2806 2807 2808 2809
static char *testDomainGetMetadata(virDomainPtr dom,
                                   int type,
                                   const char *uri,
                                   unsigned int flags)
{
    virDomainObjPtr privdom;
2810
    char *ret;
2811 2812 2813 2814

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, NULL);

2815 2816
    if (!(privdom = testDomObjFromDomain(dom)))
        return NULL;
2817

2818
    ret = virDomainObjGetMetadata(privdom, type, uri, flags);
2819

2820
    virDomainObjEndAPI(&privdom);
2821 2822 2823 2824 2825 2826 2827 2828 2829 2830
    return ret;
}

static int testDomainSetMetadata(virDomainPtr dom,
                                 int type,
                                 const char *metadata,
                                 const char *key,
                                 const char *uri,
                                 unsigned int flags)
{
2831
    testDriverPtr privconn = dom->conn->privateData;
2832
    virDomainObjPtr privdom;
2833
    int ret;
2834 2835 2836 2837

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

2838 2839
    if (!(privdom = testDomObjFromDomain(dom)))
        return -1;
2840 2841 2842

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

2845 2846 2847 2848 2849 2850
    if (ret == 0) {
        virObjectEventPtr ev = NULL;
        ev = virDomainEventMetadataChangeNewFromObj(privdom, type, uri);
        testObjectEventQueue(privconn, ev);
    }

2851
    virDomainObjEndAPI(&privdom);
2852 2853 2854 2855
    return ret;
}


2856 2857
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
2858 2859
                                      int startCell, int maxCells)
{
2860
    testDriverPtr privconn = conn->privateData;
2861 2862
    int cell;
    size_t i;
2863
    int ret = -1;
2864

2865
    testDriverLock(privconn);
2866
    if (startCell >= privconn->numCells) {
2867 2868
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("Range exceeds available cells"));
2869
        goto cleanup;
2870 2871
    }

2872 2873 2874 2875
    for (cell = startCell, i = 0;
         (cell < privconn->numCells && i < maxCells);
         ++cell, ++i) {
        freemems[i] = privconn->cells[cell].mem;
2876
    }
2877
    ret = i;
2878

2879
 cleanup:
2880
    testDriverUnlock(privconn);
2881
    return ret;
2882 2883
}

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

2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946
static unsigned long long
testNodeGetFreeMemory(virConnectPtr conn)
{
    testDriverPtr privconn = conn->privateData;
    unsigned int freeMem = 0;
    size_t i;

    testDriverLock(privconn);

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

    testDriverUnlock(privconn);
    return freeMem;
}

2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970
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;
}

2971 2972
static int testDomainCreateWithFlags(virDomainPtr domain, unsigned int flags)
{
2973
    testDriverPtr privconn = domain->conn->privateData;
2974
    virDomainObjPtr privdom;
2975
    virObjectEventPtr event = NULL;
2976
    int ret = -1;
2977

2978 2979
    virCheckFlags(0, -1);

2980
    testDriverLock(privconn);
2981

2982
    if (!(privdom = testDomObjFromDomain(domain)))
2983
        goto cleanup;
2984

J
Jiri Denemark 已提交
2985
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_SHUTOFF) {
2986 2987
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Domain '%s' is already running"), domain->name);
2988
        goto cleanup;
2989 2990
    }

2991
    if (testDomainStartState(privconn, privdom,
J
Jiri Denemark 已提交
2992
                             VIR_DOMAIN_RUNNING_BOOTED) < 0)
2993 2994 2995
        goto cleanup;
    domain->id = privdom->def->id;

2996
    event = virDomainEventLifecycleNewFromObj(privdom,
2997 2998
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
2999
    ret = 0;
3000

3001
 cleanup:
3002
    virDomainObjEndAPI(&privdom);
3003
    testObjectEventQueue(privconn, event);
3004
    testDriverUnlock(privconn);
3005
    return ret;
3006 3007
}

3008 3009
static int testDomainCreate(virDomainPtr domain)
{
3010 3011 3012
    return testDomainCreateWithFlags(domain, 0);
}

3013 3014 3015
static int testDomainUndefineFlags(virDomainPtr domain,
                                   unsigned int flags)
{
3016
    testDriverPtr privconn = domain->conn->privateData;
3017
    virDomainObjPtr privdom;
3018
    virObjectEventPtr event = NULL;
3019
    int nsnapshots;
3020
    int ret = -1;
3021

3022 3023
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
                  VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
3024

3025

3026
    if (!(privdom = testDomObjFromDomain(domain)))
3027
        goto cleanup;
3028

C
Cole Robinson 已提交
3029 3030 3031 3032 3033 3034 3035 3036
    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;
    }

3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054
    /* 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. */
    }

3055
    event = virDomainEventLifecycleNewFromObj(privdom,
3056 3057
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
C
Cole Robinson 已提交
3058 3059
    privdom->hasManagedSave = false;

3060
    if (virDomainObjIsActive(privdom))
3061
        privdom->persistent = 0;
3062 3063
    else
        virDomainObjListRemove(privconn->domains, privdom);
3064

3065
    ret = 0;
3066

3067
 cleanup:
3068
    virDomainObjEndAPI(&privdom);
3069
    testObjectEventQueue(privconn, event);
3070
    return ret;
3071 3072
}

3073 3074 3075 3076 3077
static int testDomainUndefine(virDomainPtr domain)
{
    return testDomainUndefineFlags(domain, 0);
}

3078 3079 3080
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
3081 3082
    virDomainObjPtr privdom;

3083 3084
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3085

3086
    *autostart = privdom->autostart;
3087

3088
    virDomainObjEndAPI(&privdom);
3089
    return 0;
3090 3091 3092 3093 3094 3095
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
3096 3097
    virDomainObjPtr privdom;

3098 3099
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3100

3101
    privdom->autostart = autostart ? 1 : 0;
3102

3103
    virDomainObjEndAPI(&privdom);
3104
    return 0;
3105
}
3106

3107
static char *testDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED,
3108 3109
                                        int *nparams)
{
3110 3111
    char *type = NULL;

3112 3113 3114
    if (nparams)
        *nparams = 1;

3115
    ignore_value(VIR_STRDUP(type, "fair"));
3116

3117 3118 3119
    return type;
}

3120
static int
3121 3122 3123 3124
testDomainGetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int *nparams,
                                      unsigned int flags)
3125
{
3126
    virDomainObjPtr privdom;
3127
    int ret = -1;
3128

3129 3130
    virCheckFlags(0, -1);

3131 3132
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3133

3134 3135
    if (virTypedParameterAssign(params, VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, 50) < 0)
3136
        goto cleanup;
3137 3138
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
3139 3140

    *nparams = 1;
3141 3142
    ret = 0;

3143
 cleanup:
3144
    virDomainObjEndAPI(&privdom);
3145
    return ret;
3146
}
3147

3148
static int
3149 3150 3151
testDomainGetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int *nparams)
3152
{
3153
    return testDomainGetSchedulerParametersFlags(domain, params, nparams, 0);
3154
}
3155

3156
static int
3157 3158 3159 3160
testDomainSetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int nparams,
                                      unsigned int flags)
3161
{
3162
    virDomainObjPtr privdom;
3163 3164
    int ret = -1;
    size_t i;
3165

3166
    virCheckFlags(0, -1);
3167 3168 3169 3170
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
3171
        return -1;
3172

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

3176
    for (i = 0; i < nparams; i++) {
3177 3178 3179
        if (STREQ(params[i].field, VIR_DOMAIN_SCHEDULER_WEIGHT)) {
            /* XXX */
            /*privdom->weight = params[i].value.ui;*/
3180
        }
3181
    }
3182

3183 3184
    ret = 0;

3185
    virDomainObjEndAPI(&privdom);
3186
    return ret;
3187 3188
}

3189
static int
3190 3191 3192
testDomainSetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int nparams)
3193
{
3194
    return testDomainSetSchedulerParametersFlags(domain, params, nparams, 0);
3195 3196
}

3197 3198
static int testDomainBlockStats(virDomainPtr domain,
                                const char *path,
3199
                                virDomainBlockStatsPtr stats)
3200 3201 3202 3203
{
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
3204
    int ret = -1;
3205

3206 3207 3208 3209 3210 3211
    if (!*path) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("summary statistics are not supported yet"));
        return ret;
    }

3212 3213
    if (!(privdom = testDomObjFromDomain(domain)))
        return ret;
3214

3215 3216 3217 3218 3219 3220
    if (!virDomainObjIsActive(privdom)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto error;
    }

3221
    if (virDomainDiskIndexByName(privdom->def, path, false) < 0) {
3222 3223
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path: %s"), path);
3224 3225 3226 3227
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
3228
        virReportSystemError(errno,
3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241
                             "%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;
3242
 error:
3243
    virDomainObjEndAPI(&privdom);
3244 3245 3246
    return ret;
}

3247 3248 3249 3250
static int
testDomainInterfaceStats(virDomainPtr domain,
                         const char *device,
                         virDomainInterfaceStatsPtr stats)
3251 3252 3253 3254
{
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
M
Michal Privoznik 已提交
3255 3256 3257
    virDomainNetDefPtr net = NULL;
    int ret = -1;

3258

3259 3260
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3261

3262 3263 3264 3265 3266 3267
    if (!virDomainObjIsActive(privdom)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto error;
    }

3268
    if (!(net = virDomainNetFind(privdom->def, device)))
3269 3270 3271
        goto error;

    if (gettimeofday(&tv, NULL) < 0) {
3272
        virReportSystemError(errno,
3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288
                             "%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;
3289
 error:
3290
    virDomainObjEndAPI(&privdom);
3291 3292 3293
    return ret;
}

3294

3295 3296 3297 3298
static virNetworkObjPtr
testNetworkObjFindByUUID(testDriverPtr privconn,
                         const unsigned char *uuid)
{
3299
    virNetworkObjPtr obj;
3300 3301
    char uuidstr[VIR_UUID_STRING_BUFLEN];

3302
    if (!(obj = virNetworkObjFindByUUID(privconn->networks, uuid))) {
3303 3304 3305 3306 3307 3308
        virUUIDFormat(uuid, uuidstr);
        virReportError(VIR_ERR_NO_NETWORK,
                       _("no network with matching uuid '%s'"),
                       uuidstr);
    }

3309
    return obj;
3310 3311 3312
}


3313 3314 3315
static virNetworkPtr
testNetworkLookupByUUID(virConnectPtr conn,
                        const unsigned char *uuid)
3316
{
3317
    testDriverPtr privconn = conn->privateData;
3318
    virNetworkObjPtr obj;
3319
    virNetworkDefPtr def;
3320
    virNetworkPtr net = NULL;
3321

3322
    if (!(obj = testNetworkObjFindByUUID(privconn, uuid)))
3323
        goto cleanup;
3324
    def = virNetworkObjGetDef(obj);
3325

3326
    net = virGetNetwork(conn, def->name, def->uuid);
3327

3328
 cleanup:
3329 3330
    virNetworkObjEndAPI(&obj);
    return net;
3331
}
3332

3333 3334 3335 3336 3337

static virNetworkObjPtr
testNetworkObjFindByName(testDriverPtr privconn,
                         const char *name)
{
3338
    virNetworkObjPtr obj;
3339

3340
    if (!(obj = virNetworkObjFindByName(privconn->networks, name)))
3341 3342 3343 3344
        virReportError(VIR_ERR_NO_NETWORK,
                       _("no network with matching name '%s'"),
                       name);

3345
    return obj;
3346 3347 3348
}


3349 3350 3351
static virNetworkPtr
testNetworkLookupByName(virConnectPtr conn,
                        const char *name)
3352
{
3353
    testDriverPtr privconn = conn->privateData;
3354
    virNetworkObjPtr obj;
3355
    virNetworkDefPtr def;
3356
    virNetworkPtr net = NULL;
3357

3358
    if (!(obj = testNetworkObjFindByName(privconn, name)))
3359
        goto cleanup;
3360
    def = virNetworkObjGetDef(obj);
3361

3362
    net = virGetNetwork(conn, def->name, def->uuid);
3363

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


3370 3371
static int
testConnectNumOfNetworks(virConnectPtr conn)
3372
{
3373
    testDriverPtr privconn = conn->privateData;
3374
    int numActive;
3375

3376 3377
    numActive = virNetworkObjListNumOfNetworks(privconn->networks,
                                               true, NULL, conn);
3378
    return numActive;
3379 3380
}

3381 3382 3383 3384

static int
testConnectListNetworks(virConnectPtr conn,
                        char **const names,
3385
                        int maxnames)
3386
{
3387
    testDriverPtr privconn = conn->privateData;
3388
    int n;
3389

3390
    n = virNetworkObjListGetNames(privconn->networks,
3391
                                  true, names, maxnames, NULL, conn);
3392
    return n;
3393 3394
}

3395 3396 3397

static int
testConnectNumOfDefinedNetworks(virConnectPtr conn)
3398
{
3399
    testDriverPtr privconn = conn->privateData;
3400
    int numInactive;
3401

3402 3403
    numInactive = virNetworkObjListNumOfNetworks(privconn->networks,
                                                 false, NULL, conn);
3404
    return numInactive;
3405 3406
}

3407 3408 3409 3410

static int
testConnectListDefinedNetworks(virConnectPtr conn,
                               char **const names,
3411
                               int maxnames)
3412
{
3413
    testDriverPtr privconn = conn->privateData;
3414
    int n;
3415

3416
    n = virNetworkObjListGetNames(privconn->networks,
3417
                                  false, names, maxnames, NULL, conn);
3418
    return n;
3419 3420
}

3421

3422
static int
3423
testConnectListAllNetworks(virConnectPtr conn,
3424 3425 3426
                           virNetworkPtr **nets,
                           unsigned int flags)
{
3427
    testDriverPtr privconn = conn->privateData;
3428 3429 3430

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

3431
    return virNetworkObjListExport(conn, privconn->networks, nets, NULL, flags);
3432
}
3433

3434 3435 3436

static int
testNetworkIsActive(virNetworkPtr net)
3437
{
3438
    testDriverPtr privconn = net->conn->privateData;
3439 3440 3441
    virNetworkObjPtr obj;
    int ret = -1;

3442
    if (!(obj = testNetworkObjFindByUUID(privconn, net->uuid)))
3443
        goto cleanup;
3444

3445 3446
    ret = virNetworkObjIsActive(obj);

3447
 cleanup:
3448
    virNetworkObjEndAPI(&obj);
3449 3450 3451
    return ret;
}

3452 3453 3454

static int
testNetworkIsPersistent(virNetworkPtr net)
3455
{
3456
    testDriverPtr privconn = net->conn->privateData;
3457 3458 3459
    virNetworkObjPtr obj;
    int ret = -1;

3460
    if (!(obj = testNetworkObjFindByUUID(privconn, net->uuid)))
3461
        goto cleanup;
3462

3463
    ret = virNetworkObjIsPersistent(obj);
3464

3465
 cleanup:
3466
    virNetworkObjEndAPI(&obj);
3467 3468 3469 3470
    return ret;
}


3471 3472
static virNetworkPtr
testNetworkCreateXML(virConnectPtr conn, const char *xml)
3473
{
3474
    testDriverPtr privconn = conn->privateData;
3475
    virNetworkDefPtr newDef;
3476
    virNetworkObjPtr obj = NULL;
3477
    virNetworkDefPtr def;
3478
    virNetworkPtr net = NULL;
3479
    virObjectEventPtr event = NULL;
3480

3481
    if ((newDef = virNetworkDefParseString(xml)) == NULL)
3482
        goto cleanup;
3483

3484
    if (!(obj = virNetworkObjAssignDef(privconn->networks, newDef,
3485 3486
                                       VIR_NETWORK_OBJ_LIST_ADD_LIVE |
                                       VIR_NETWORK_OBJ_LIST_ADD_CHECK_LIVE)))
3487
        goto cleanup;
3488 3489
    newDef = NULL;
    def = virNetworkObjGetDef(obj);
3490
    virNetworkObjSetActive(obj, true);
3491

3492
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
3493 3494
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3495

3496
    net = virGetNetwork(conn, def->name, def->uuid);
3497

3498
 cleanup:
3499
    virNetworkDefFree(newDef);
3500
    testObjectEventQueue(privconn, event);
3501 3502
    virNetworkObjEndAPI(&obj);
    return net;
3503 3504
}

3505 3506 3507 3508

static virNetworkPtr
testNetworkDefineXML(virConnectPtr conn,
                     const char *xml)
3509
{
3510
    testDriverPtr privconn = conn->privateData;
3511
    virNetworkDefPtr newDef;
3512
    virNetworkObjPtr obj = NULL;
3513
    virNetworkDefPtr def;
3514
    virNetworkPtr net = NULL;
3515
    virObjectEventPtr event = NULL;
3516

3517
    if ((newDef = virNetworkDefParseString(xml)) == NULL)
3518
        goto cleanup;
3519

3520
    if (!(obj = virNetworkObjAssignDef(privconn->networks, newDef, 0)))
3521
        goto cleanup;
3522 3523
    newDef = NULL;
    def = virNetworkObjGetDef(obj);
3524

3525
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
3526 3527
                                        VIR_NETWORK_EVENT_DEFINED,
                                        0);
3528

3529
    net = virGetNetwork(conn, def->name, def->uuid);
3530

3531
 cleanup:
3532
    virNetworkDefFree(newDef);
3533
    testObjectEventQueue(privconn, event);
3534 3535
    virNetworkObjEndAPI(&obj);
    return net;
3536 3537
}

3538 3539

static int
3540
testNetworkUndefine(virNetworkPtr net)
3541
{
3542 3543
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3544
    int ret = -1;
3545
    virObjectEventPtr event = NULL;
3546

3547
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3548
        goto cleanup;
3549

3550
    if (virNetworkObjIsActive(obj)) {
3551
        virReportError(VIR_ERR_OPERATION_INVALID,
3552
                       _("Network '%s' is still running"), net->name);
3553
        goto cleanup;
3554 3555
    }

3556
    event = virNetworkEventLifecycleNew(net->name, net->uuid,
3557 3558
                                        VIR_NETWORK_EVENT_UNDEFINED,
                                        0);
3559

3560
    virNetworkObjRemoveInactive(privconn->networks, obj);
3561
    ret = 0;
3562

3563
 cleanup:
3564
    testObjectEventQueue(privconn, event);
3565
    virNetworkObjEndAPI(&obj);
3566
    return ret;
3567 3568
}

3569

3570 3571 3572 3573 3574 3575 3576 3577
static int
testNetworkUpdate(virNetworkPtr net,
                  unsigned int command,
                  unsigned int section,
                  int parentIndex,
                  const char *xml,
                  unsigned int flags)
{
3578
    testDriverPtr privconn = net->conn->privateData;
3579
    virNetworkObjPtr obj = NULL;
3580 3581 3582 3583 3584 3585
    int isActive, ret = -1;

    virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
                  VIR_NETWORK_UPDATE_AFFECT_CONFIG,
                  -1);

3586
    if (!(obj = testNetworkObjFindByUUID(privconn, net->uuid)))
3587 3588 3589 3590 3591
        goto cleanup;

    /* VIR_NETWORK_UPDATE_AFFECT_CURRENT means "change LIVE if network
     * is active, else change CONFIG
    */
3592
    isActive = virNetworkObjIsActive(obj);
3593 3594 3595 3596 3597 3598 3599 3600 3601 3602
    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 */
3603
    if (virNetworkObjUpdate(obj, command, section, parentIndex, xml, flags) < 0)
3604 3605 3606
       goto cleanup;

    ret = 0;
3607
 cleanup:
3608
    virNetworkObjEndAPI(&obj);
3609 3610 3611
    return ret;
}

3612 3613

static int
3614
testNetworkCreate(virNetworkPtr net)
3615
{
3616 3617
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3618
    virNetworkDefPtr def;
3619
    int ret = -1;
3620
    virObjectEventPtr event = NULL;
3621

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

3626
    if (virNetworkObjIsActive(obj)) {
3627
        virReportError(VIR_ERR_OPERATION_INVALID,
3628
                       _("Network '%s' is already running"), net->name);
3629
        goto cleanup;
3630 3631
    }

3632
    virNetworkObjSetActive(obj, true);
3633
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
3634 3635
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3636
    ret = 0;
3637

3638
 cleanup:
3639
    testObjectEventQueue(privconn, event);
3640
    virNetworkObjEndAPI(&obj);
3641
    return ret;
3642 3643
}

3644 3645

static int
3646
testNetworkDestroy(virNetworkPtr net)
3647
{
3648 3649
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3650
    virNetworkDefPtr def;
3651
    int ret = -1;
3652
    virObjectEventPtr event = NULL;
3653

3654
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3655
        goto cleanup;
3656
    def = virNetworkObjGetDef(obj);
3657

3658
    virNetworkObjSetActive(obj, false);
3659
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
3660 3661
                                        VIR_NETWORK_EVENT_STOPPED,
                                        0);
3662
    if (!virNetworkObjIsPersistent(obj))
3663
        virNetworkObjRemoveInactive(privconn->networks, obj);
3664

3665 3666
    ret = 0;

3667
 cleanup:
3668
    testObjectEventQueue(privconn, event);
3669
    virNetworkObjEndAPI(&obj);
3670
    return ret;
3671 3672
}

3673 3674

static char *
3675
testNetworkGetXMLDesc(virNetworkPtr net,
3676
                      unsigned int flags)
3677
{
3678 3679
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3680
    char *ret = NULL;
3681

E
Eric Blake 已提交
3682 3683
    virCheckFlags(0, NULL);

3684
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3685
        goto cleanup;
3686

3687
    ret = virNetworkDefFormat(virNetworkObjGetDef(obj), flags);
3688

3689
 cleanup:
3690
    virNetworkObjEndAPI(&obj);
3691
    return ret;
3692 3693
}

3694 3695

static char *
3696
testNetworkGetBridgeName(virNetworkPtr net)
3697
{
3698
    testDriverPtr privconn = net->conn->privateData;
3699
    char *bridge = NULL;
3700
    virNetworkObjPtr obj;
3701
    virNetworkDefPtr def;
3702

3703
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3704
        goto cleanup;
3705
    def = virNetworkObjGetDef(obj);
3706

3707
    if (!(def->bridge)) {
3708 3709
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("network '%s' does not have a bridge name."),
3710
                       def->name);
3711 3712 3713
        goto cleanup;
    }

3714
    ignore_value(VIR_STRDUP(bridge, def->bridge));
3715

3716
 cleanup:
3717
    virNetworkObjEndAPI(&obj);
3718 3719 3720
    return bridge;
}

3721 3722

static int
3723
testNetworkGetAutostart(virNetworkPtr net,
3724
                        int *autostart)
3725
{
3726 3727
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3728
    int ret = -1;
3729

3730
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3731
        goto cleanup;
3732

3733
    *autostart = virNetworkObjIsAutostart(obj) ? 1 : 0;
3734 3735
    ret = 0;

3736
 cleanup:
3737
    virNetworkObjEndAPI(&obj);
3738
    return ret;
3739 3740
}

3741 3742

static int
3743
testNetworkSetAutostart(virNetworkPtr net,
3744
                        int autostart)
3745
{
3746 3747
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
3748
    bool new_autostart = (autostart != 0);
3749
    int ret = -1;
3750

3751
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
3752
        goto cleanup;
3753

3754 3755
    virNetworkObjSetAutostart(obj, new_autostart);

3756 3757
    ret = 0;

3758
 cleanup:
3759
    virNetworkObjEndAPI(&obj);
3760
    return ret;
3761
}
3762

C
Cole Robinson 已提交
3763

L
Laine Stump 已提交
3764 3765 3766 3767 3768
/*
 * Physical host interface routines
 */


3769 3770 3771 3772
static virInterfaceObjPtr
testInterfaceObjFindByName(testDriverPtr privconn,
                           const char *name)
{
3773
    virInterfaceObjPtr obj;
3774 3775

    testDriverLock(privconn);
3776
    obj = virInterfaceObjListFindByName(privconn->ifaces, name);
3777 3778
    testDriverUnlock(privconn);

3779
    if (!obj)
3780 3781 3782 3783
        virReportError(VIR_ERR_NO_INTERFACE,
                       _("no interface with matching name '%s'"),
                       name);

3784
    return obj;
3785 3786 3787
}


3788 3789
static int
testConnectNumOfInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3790
{
3791
    testDriverPtr privconn = conn->privateData;
3792
    int ninterfaces;
L
Laine Stump 已提交
3793 3794

    testDriverLock(privconn);
3795
    ninterfaces = virInterfaceObjListNumOfInterfaces(privconn->ifaces, true);
L
Laine Stump 已提交
3796
    testDriverUnlock(privconn);
3797
    return ninterfaces;
L
Laine Stump 已提交
3798 3799
}

3800 3801 3802 3803 3804

static int
testConnectListInterfaces(virConnectPtr conn,
                          char **const names,
                          int maxnames)
L
Laine Stump 已提交
3805
{
3806
    testDriverPtr privconn = conn->privateData;
3807
    int nnames;
L
Laine Stump 已提交
3808 3809

    testDriverLock(privconn);
3810 3811
    nnames = virInterfaceObjListGetNames(privconn->ifaces, true,
                                         names, maxnames);
L
Laine Stump 已提交
3812 3813
    testDriverUnlock(privconn);

3814
    return nnames;
L
Laine Stump 已提交
3815 3816
}

3817 3818 3819

static int
testConnectNumOfDefinedInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3820
{
3821
    testDriverPtr privconn = conn->privateData;
3822
    int ninterfaces;
L
Laine Stump 已提交
3823 3824

    testDriverLock(privconn);
3825
    ninterfaces = virInterfaceObjListNumOfInterfaces(privconn->ifaces, false);
L
Laine Stump 已提交
3826
    testDriverUnlock(privconn);
3827
    return ninterfaces;
L
Laine Stump 已提交
3828 3829
}

3830 3831 3832 3833 3834

static int
testConnectListDefinedInterfaces(virConnectPtr conn,
                                 char **const names,
                                 int maxnames)
L
Laine Stump 已提交
3835
{
3836
    testDriverPtr privconn = conn->privateData;
3837
    int nnames;
L
Laine Stump 已提交
3838 3839

    testDriverLock(privconn);
3840 3841
    nnames = virInterfaceObjListGetNames(privconn->ifaces, false,
                                         names, maxnames);
L
Laine Stump 已提交
3842 3843
    testDriverUnlock(privconn);

3844
    return nnames;
L
Laine Stump 已提交
3845 3846
}

3847 3848 3849 3850

static virInterfacePtr
testInterfaceLookupByName(virConnectPtr conn,
                          const char *name)
L
Laine Stump 已提交
3851
{
3852
    testDriverPtr privconn = conn->privateData;
3853
    virInterfaceObjPtr obj;
3854
    virInterfaceDefPtr def;
L
Laine Stump 已提交
3855 3856
    virInterfacePtr ret = NULL;

3857
    if (!(obj = testInterfaceObjFindByName(privconn, name)))
3858
        return NULL;
3859
    def = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
3860

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

3863
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
3864 3865 3866
    return ret;
}

3867 3868 3869 3870

static virInterfacePtr
testInterfaceLookupByMACString(virConnectPtr conn,
                               const char *mac)
L
Laine Stump 已提交
3871
{
3872
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3873
    int ifacect;
3874
    char *ifacenames[] = { NULL, NULL };
L
Laine Stump 已提交
3875 3876 3877
    virInterfacePtr ret = NULL;

    testDriverLock(privconn);
3878 3879
    ifacect = virInterfaceObjListFindByMACString(privconn->ifaces, mac,
                                                 ifacenames, 2);
L
Laine Stump 已提交
3880 3881 3882
    testDriverUnlock(privconn);

    if (ifacect == 0) {
3883 3884
        virReportError(VIR_ERR_NO_INTERFACE,
                       _("no interface with matching mac '%s'"), mac);
L
Laine Stump 已提交
3885 3886 3887 3888
        goto cleanup;
    }

    if (ifacect > 1) {
3889
        virReportError(VIR_ERR_MULTIPLE_INTERFACES, NULL);
L
Laine Stump 已提交
3890 3891 3892
        goto cleanup;
    }

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

3895
 cleanup:
3896 3897
    VIR_FREE(ifacenames[0]);
    VIR_FREE(ifacenames[1]);
L
Laine Stump 已提交
3898 3899 3900
    return ret;
}

3901 3902 3903

static int
testInterfaceIsActive(virInterfacePtr iface)
3904
{
3905
    testDriverPtr privconn = iface->conn->privateData;
3906 3907 3908
    virInterfaceObjPtr obj;
    int ret = -1;

3909
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
3910
        return -1;
3911

3912 3913
    ret = virInterfaceObjIsActive(obj);

3914
    virInterfaceObjEndAPI(&obj);
3915 3916 3917
    return ret;
}

3918 3919 3920 3921

static int
testInterfaceChangeBegin(virConnectPtr conn,
                         unsigned int flags)
3922
{
3923
    testDriverPtr privconn = conn->privateData;
3924 3925
    int ret = -1;

E
Eric Blake 已提交
3926 3927
    virCheckFlags(0, -1);

3928 3929
    testDriverLock(privconn);
    if (privconn->transaction_running) {
3930
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3931
                       _("there is another transaction running."));
3932 3933 3934 3935 3936
        goto cleanup;
    }

    privconn->transaction_running = true;

3937
    if (!(privconn->backupIfaces = virInterfaceObjListClone(privconn->ifaces)))
3938 3939 3940
        goto cleanup;

    ret = 0;
3941
 cleanup:
3942 3943 3944 3945
    testDriverUnlock(privconn);
    return ret;
}

3946 3947 3948 3949

static int
testInterfaceChangeCommit(virConnectPtr conn,
                          unsigned int flags)
3950
{
3951
    testDriverPtr privconn = conn->privateData;
3952 3953
    int ret = -1;

E
Eric Blake 已提交
3954 3955
    virCheckFlags(0, -1);

3956 3957 3958
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3959
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3960 3961
                       _("no transaction running, "
                         "nothing to be committed."));
3962 3963 3964
        goto cleanup;
    }

3965
    virObjectUnref(privconn->backupIfaces);
3966 3967 3968 3969
    privconn->transaction_running = false;

    ret = 0;

3970
 cleanup:
3971 3972 3973 3974 3975
    testDriverUnlock(privconn);

    return ret;
}

3976 3977 3978 3979

static int
testInterfaceChangeRollback(virConnectPtr conn,
                            unsigned int flags)
3980
{
3981
    testDriverPtr privconn = conn->privateData;
3982 3983
    int ret = -1;

E
Eric Blake 已提交
3984 3985
    virCheckFlags(0, -1);

3986 3987 3988
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3989
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3990 3991
                       _("no transaction running, "
                         "nothing to rollback."));
3992 3993 3994
        goto cleanup;
    }

3995
    virObjectUnref(privconn->ifaces);
3996 3997
    privconn->ifaces = privconn->backupIfaces;
    privconn->backupIfaces = NULL;
3998 3999 4000 4001 4002

    privconn->transaction_running = false;

    ret = 0;

4003
 cleanup:
4004 4005 4006
    testDriverUnlock(privconn);
    return ret;
}
4007

4008 4009 4010 4011

static char *
testInterfaceGetXMLDesc(virInterfacePtr iface,
                        unsigned int flags)
L
Laine Stump 已提交
4012
{
4013
    testDriverPtr privconn = iface->conn->privateData;
4014
    virInterfaceObjPtr obj;
4015
    virInterfaceDefPtr def;
L
Laine Stump 已提交
4016 4017
    char *ret = NULL;

E
Eric Blake 已提交
4018 4019
    virCheckFlags(0, NULL);

4020
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
4021
        return NULL;
4022
    def = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
4023

4024
    ret = virInterfaceDefFormat(def);
L
Laine Stump 已提交
4025

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


4031 4032 4033 4034
static virInterfacePtr
testInterfaceDefineXML(virConnectPtr conn,
                       const char *xmlStr,
                       unsigned int flags)
L
Laine Stump 已提交
4035
{
4036
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
4037
    virInterfaceDefPtr def;
4038
    virInterfaceObjPtr obj = NULL;
4039
    virInterfaceDefPtr objdef;
L
Laine Stump 已提交
4040 4041
    virInterfacePtr ret = NULL;

E
Eric Blake 已提交
4042 4043
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
4044
    testDriverLock(privconn);
4045
    if ((def = virInterfaceDefParseString(xmlStr)) == NULL)
L
Laine Stump 已提交
4046 4047
        goto cleanup;

4048
    if ((obj = virInterfaceObjListAssignDef(privconn->ifaces, def)) == NULL)
L
Laine Stump 已提交
4049 4050
        goto cleanup;
    def = NULL;
4051
    objdef = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
4052

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

4055
 cleanup:
L
Laine Stump 已提交
4056
    virInterfaceDefFree(def);
4057
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
4058 4059 4060 4061
    testDriverUnlock(privconn);
    return ret;
}

4062 4063 4064

static int
testInterfaceUndefine(virInterfacePtr iface)
L
Laine Stump 已提交
4065
{
4066
    testDriverPtr privconn = iface->conn->privateData;
4067
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
4068

4069
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
4070
        return -1;
L
Laine Stump 已提交
4071

4072
    virInterfaceObjListRemove(privconn->ifaces, obj);
4073
    virObjectUnref(obj);
L
Laine Stump 已提交
4074

4075
    return 0;
L
Laine Stump 已提交
4076 4077
}

4078 4079 4080 4081

static int
testInterfaceCreate(virInterfacePtr iface,
                    unsigned int flags)
L
Laine Stump 已提交
4082
{
4083
    testDriverPtr privconn = iface->conn->privateData;
4084
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
4085 4086
    int ret = -1;

E
Eric Blake 已提交
4087 4088
    virCheckFlags(0, -1);

4089
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
4090
        return -1;
L
Laine Stump 已提交
4091

4092
    if (virInterfaceObjIsActive(obj)) {
4093
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
4094 4095 4096
        goto cleanup;
    }

4097
    virInterfaceObjSetActive(obj, true);
L
Laine Stump 已提交
4098 4099
    ret = 0;

4100
 cleanup:
4101
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
4102 4103 4104
    return ret;
}

4105 4106 4107 4108

static int
testInterfaceDestroy(virInterfacePtr iface,
                     unsigned int flags)
L
Laine Stump 已提交
4109
{
4110
    testDriverPtr privconn = iface->conn->privateData;
4111
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
4112 4113
    int ret = -1;

E
Eric Blake 已提交
4114 4115
    virCheckFlags(0, -1);

4116
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
4117
        return -1;
L
Laine Stump 已提交
4118

4119
    if (!virInterfaceObjIsActive(obj)) {
4120
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
4121 4122 4123
        goto cleanup;
    }

4124
    virInterfaceObjSetActive(obj, false);
L
Laine Stump 已提交
4125 4126
    ret = 0;

4127
 cleanup:
4128
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
4129 4130 4131 4132 4133
    return ret;
}



C
Cole Robinson 已提交
4134 4135 4136 4137
/*
 * Storage Driver routines
 */

4138
static int
4139
testStoragePoolObjSetDefaults(virStoragePoolObjPtr obj)
4140
{
4141
    char *configFile;
4142
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4143

4144 4145 4146
    def->capacity = defaultPoolCap;
    def->allocation = defaultPoolAlloc;
    def->available = defaultPoolCap - defaultPoolAlloc;
C
Cole Robinson 已提交
4147

4148 4149 4150 4151 4152
    if (VIR_STRDUP(configFile, "") < 0)
        return -1;

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

4155

4156 4157 4158 4159
static virStoragePoolObjPtr
testStoragePoolObjFindByName(testDriverPtr privconn,
                             const char *name)
{
4160
    virStoragePoolObjPtr obj;
4161 4162

    testDriverLock(privconn);
4163
    obj = virStoragePoolObjFindByName(privconn->pools, name);
4164 4165
    testDriverUnlock(privconn);

4166
    if (!obj)
4167 4168 4169 4170
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       name);

4171
    return obj;
4172 4173 4174
}


4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186
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);
4187
        virStoragePoolObjEndAPI(&obj);
4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206
        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);
4207
        virStoragePoolObjEndAPI(&obj);
4208 4209 4210 4211 4212 4213 4214
        return NULL;
    }

    return obj;
}


4215 4216 4217 4218
static virStoragePoolObjPtr
testStoragePoolObjFindByUUID(testDriverPtr privconn,
                             const unsigned char *uuid)
{
4219
    virStoragePoolObjPtr obj;
4220 4221 4222
    char uuidstr[VIR_UUID_STRING_BUFLEN];

    testDriverLock(privconn);
4223
    obj = virStoragePoolObjFindByUUID(privconn->pools, uuid);
4224 4225
    testDriverUnlock(privconn);

4226
    if (!obj) {
4227 4228 4229 4230 4231 4232
        virUUIDFormat(uuid, uuidstr);
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching uuid '%s'"),
                       uuidstr);
    }

4233
    return obj;
4234 4235 4236
}


C
Cole Robinson 已提交
4237 4238
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
4239 4240
                            const unsigned char *uuid)
{
4241
    testDriverPtr privconn = conn->privateData;
4242
    virStoragePoolObjPtr obj;
4243
    virStoragePoolDefPtr def;
4244
    virStoragePoolPtr pool = NULL;
C
Cole Robinson 已提交
4245

4246
    if (!(obj = testStoragePoolObjFindByUUID(privconn, uuid)))
4247
        return NULL;
4248
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4249

4250
    pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
4251

4252
    virStoragePoolObjEndAPI(&obj);
4253
    return pool;
C
Cole Robinson 已提交
4254 4255
}

4256

C
Cole Robinson 已提交
4257 4258
static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
4259 4260
                            const char *name)
{
4261
    testDriverPtr privconn = conn->privateData;
4262
    virStoragePoolObjPtr obj;
4263
    virStoragePoolDefPtr def;
4264
    virStoragePoolPtr pool = NULL;
C
Cole Robinson 已提交
4265

4266
    if (!(obj = testStoragePoolObjFindByName(privconn, name)))
4267
        return NULL;
4268
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4269

4270
    pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
4271

4272
    virStoragePoolObjEndAPI(&obj);
4273
    return pool;
C
Cole Robinson 已提交
4274 4275
}

4276

C
Cole Robinson 已提交
4277
static virStoragePoolPtr
4278 4279
testStoragePoolLookupByVolume(virStorageVolPtr vol)
{
C
Cole Robinson 已提交
4280 4281 4282
    return testStoragePoolLookupByName(vol->conn, vol->pool);
}

4283

C
Cole Robinson 已提交
4284
static int
4285 4286
testConnectNumOfStoragePools(virConnectPtr conn)
{
4287
    testDriverPtr privconn = conn->privateData;
4288
    int numActive = 0;
C
Cole Robinson 已提交
4289

4290
    testDriverLock(privconn);
4291
    numActive = virStoragePoolObjNumOfStoragePools(privconn->pools, conn,
4292
                                                   true, NULL);
4293
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4294 4295 4296 4297

    return numActive;
}

4298

C
Cole Robinson 已提交
4299
static int
4300 4301
testConnectListStoragePools(virConnectPtr conn,
                            char **const names,
4302
                            int maxnames)
4303
{
4304
    testDriverPtr privconn = conn->privateData;
4305
    int n = 0;
C
Cole Robinson 已提交
4306

4307
    testDriverLock(privconn);
4308
    n = virStoragePoolObjGetNames(privconn->pools, conn, true, NULL,
4309
                                  names, maxnames);
4310
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4311 4312 4313 4314

    return n;
}

4315

C
Cole Robinson 已提交
4316
static int
4317 4318
testConnectNumOfDefinedStoragePools(virConnectPtr conn)
{
4319
    testDriverPtr privconn = conn->privateData;
4320
    int numInactive = 0;
C
Cole Robinson 已提交
4321

4322
    testDriverLock(privconn);
4323
    numInactive = virStoragePoolObjNumOfStoragePools(privconn->pools, conn,
4324
                                                     false, NULL);
4325
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4326 4327 4328 4329

    return numInactive;
}

4330

C
Cole Robinson 已提交
4331
static int
4332 4333
testConnectListDefinedStoragePools(virConnectPtr conn,
                                   char **const names,
4334
                                   int maxnames)
4335
{
4336
    testDriverPtr privconn = conn->privateData;
4337
    int n = 0;
C
Cole Robinson 已提交
4338

4339
    testDriverLock(privconn);
4340
    n = virStoragePoolObjGetNames(privconn->pools, conn, false, NULL,
4341
                                  names, maxnames);
4342
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4343 4344 4345 4346

    return n;
}

4347

4348
static int
4349 4350 4351
testConnectListAllStoragePools(virConnectPtr conn,
                               virStoragePoolPtr **pools,
                               unsigned int flags)
4352
{
4353
    testDriverPtr privconn = conn->privateData;
4354 4355 4356 4357 4358
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

    testDriverLock(privconn);
4359
    ret = virStoragePoolObjListExport(conn, privconn->pools, pools,
4360
                                      NULL, flags);
4361 4362 4363 4364
    testDriverUnlock(privconn);

    return ret;
}
C
Cole Robinson 已提交
4365

4366 4367 4368

static int
testStoragePoolIsActive(virStoragePoolPtr pool)
4369
{
4370
    testDriverPtr privconn = pool->conn->privateData;
4371 4372 4373
    virStoragePoolObjPtr obj;
    int ret = -1;

4374
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
4375
        goto cleanup;
4376

4377 4378
    ret = virStoragePoolObjIsActive(obj);

4379
 cleanup:
4380
    if (obj)
4381
        virStoragePoolObjEndAPI(&obj);
4382 4383 4384
    return ret;
}

4385 4386 4387

static int
testStoragePoolIsPersistent(virStoragePoolPtr pool)
4388
{
4389
    testDriverPtr privconn = pool->conn->privateData;
4390 4391 4392
    virStoragePoolObjPtr obj;
    int ret = -1;

4393
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
4394
        return -1;
4395

4396
    ret = virStoragePoolObjGetConfigFile(obj) ? 1 : 0;
4397

4398
    virStoragePoolObjEndAPI(&obj);
4399 4400 4401 4402
    return ret;
}


C
Cole Robinson 已提交
4403
static int
4404 4405
testStoragePoolCreate(virStoragePoolPtr pool,
                      unsigned int flags)
E
Eric Blake 已提交
4406
{
4407
    testDriverPtr privconn = pool->conn->privateData;
4408
    virStoragePoolObjPtr obj;
4409
    virObjectEventPtr event = NULL;
4410

E
Eric Blake 已提交
4411 4412
    virCheckFlags(0, -1);

4413 4414
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
4415

4416
    virStoragePoolObjSetActive(obj, true);
4417 4418 4419 4420

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

4422
    testObjectEventQueue(privconn, event);
4423
    virStoragePoolObjEndAPI(&obj);
4424
    return 0;
C
Cole Robinson 已提交
4425 4426
}

4427

C
Cole Robinson 已提交
4428
static char *
4429 4430 4431 4432
testConnectFindStoragePoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type,
                                  const char *srcSpec,
                                  unsigned int flags)
C
Cole Robinson 已提交
4433
{
4434 4435 4436 4437
    virStoragePoolSourcePtr source = NULL;
    int pool_type;
    char *ret = NULL;

E
Eric Blake 已提交
4438 4439
    virCheckFlags(0, NULL);

4440 4441
    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
4442 4443
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
4444 4445 4446 4447
        goto cleanup;
    }

    if (srcSpec) {
4448
        source = virStoragePoolDefParseSourceString(srcSpec, pool_type);
4449 4450 4451 4452 4453 4454 4455
        if (!source)
            goto cleanup;
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
4456
        ignore_value(VIR_STRDUP(ret, defaultPoolSourcesLogicalXML));
4457 4458 4459
        break;

    case VIR_STORAGE_POOL_NETFS:
4460
        if (!source || !source->hosts[0].name) {
4461 4462
            virReportError(VIR_ERR_INVALID_ARG,
                           "%s", _("hostname must be specified for netfs sources"));
4463 4464 4465
            goto cleanup;
        }

4466 4467
        ignore_value(virAsprintf(&ret, defaultPoolSourcesNetFSXML,
                                 source->hosts[0].name));
4468 4469 4470
        break;

    default:
4471 4472
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source discovery"), type);
4473 4474
    }

4475
 cleanup:
4476 4477
    virStoragePoolSourceFree(source);
    return ret;
C
Cole Robinson 已提交
4478 4479 4480
}


4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502
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;
4503
    virNodeDeviceObjEndAPI(&obj);
4504 4505 4506 4507 4508

    return 0;
}


C
Cole Robinson 已提交
4509
static virStoragePoolPtr
4510 4511 4512
testStoragePoolCreateXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4513
{
4514
    testDriverPtr privconn = conn->privateData;
4515
    virStoragePoolDefPtr newDef;
4516
    virStoragePoolObjPtr obj = NULL;
4517
    virStoragePoolDefPtr def;
4518
    virStoragePoolPtr pool = NULL;
4519
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
4520

E
Eric Blake 已提交
4521 4522
    virCheckFlags(0, NULL);

4523
    testDriverLock(privconn);
4524
    if (!(newDef = virStoragePoolDefParseString(xml)))
4525
        goto cleanup;
C
Cole Robinson 已提交
4526

4527
    if (virStoragePoolObjIsDuplicate(privconn->pools, newDef, true) < 0)
4528
        goto cleanup;
C
Cole Robinson 已提交
4529

4530
    if (!(obj = virStoragePoolObjAssignDef(privconn->pools, newDef)))
4531
        goto cleanup;
4532 4533
    newDef = NULL;
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4534

4535
    if (def->source.adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
4536 4537 4538 4539 4540
        /* 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,
4541 4542
                            def->source.adapter.data.fchost.wwnn,
                            def->source.adapter.data.fchost.wwpn) < 0) {
4543
            virStoragePoolObjRemove(privconn->pools, obj);
4544
            virObjectUnref(obj);
4545
            obj = NULL;
4546 4547 4548 4549
            goto cleanup;
        }
    }

4550
    if (testStoragePoolObjSetDefaults(obj) == -1) {
4551
        virStoragePoolObjRemove(privconn->pools, obj);
4552
        virObjectUnref(obj);
4553
        obj = NULL;
4554
        goto cleanup;
C
Cole Robinson 已提交
4555
    }
4556 4557 4558 4559

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

4562
    virStoragePoolObjSetActive(obj, true);
C
Cole Robinson 已提交
4563

4564
    event = virStoragePoolEventLifecycleNew(def->name, def->uuid,
4565 4566 4567
                                            VIR_STORAGE_POOL_EVENT_STARTED,
                                            0);

4568
    pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
4569

4570
 cleanup:
4571
    virStoragePoolDefFree(newDef);
4572
    testObjectEventQueue(privconn, event);
4573
    virStoragePoolObjEndAPI(&obj);
4574
    testDriverUnlock(privconn);
4575
    return pool;
C
Cole Robinson 已提交
4576 4577
}

4578

C
Cole Robinson 已提交
4579
static virStoragePoolPtr
4580 4581 4582
testStoragePoolDefineXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4583
{
4584
    testDriverPtr privconn = conn->privateData;
4585
    virStoragePoolDefPtr newDef;
4586
    virStoragePoolObjPtr obj = NULL;
4587
    virStoragePoolDefPtr def;
4588
    virStoragePoolPtr pool = NULL;
4589
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
4590

E
Eric Blake 已提交
4591 4592
    virCheckFlags(0, NULL);

4593
    testDriverLock(privconn);
4594
    if (!(newDef = virStoragePoolDefParseString(xml)))
4595
        goto cleanup;
C
Cole Robinson 已提交
4596

4597 4598 4599
    newDef->capacity = defaultPoolCap;
    newDef->allocation = defaultPoolAlloc;
    newDef->available = defaultPoolCap - defaultPoolAlloc;
C
Cole Robinson 已提交
4600

4601 4602 4603
    if (virStoragePoolObjIsDuplicate(privconn->pools, newDef, false) < 0)
        goto cleanup;

4604
    if (!(obj = virStoragePoolObjAssignDef(privconn->pools, newDef)))
4605
        goto cleanup;
4606 4607
    newDef = NULL;
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4608

4609
    event = virStoragePoolEventLifecycleNew(def->name, def->uuid,
4610 4611 4612
                                            VIR_STORAGE_POOL_EVENT_DEFINED,
                                            0);

4613
    if (testStoragePoolObjSetDefaults(obj) == -1) {
4614
        virStoragePoolObjRemove(privconn->pools, obj);
4615
        virObjectUnref(obj);
4616
        obj = NULL;
4617
        goto cleanup;
C
Cole Robinson 已提交
4618 4619
    }

4620
    pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
4621

4622
 cleanup:
4623
    virStoragePoolDefFree(newDef);
4624
    testObjectEventQueue(privconn, event);
4625
    virStoragePoolObjEndAPI(&obj);
4626
    testDriverUnlock(privconn);
4627
    return pool;
C
Cole Robinson 已提交
4628 4629
}

4630

C
Cole Robinson 已提交
4631
static int
4632 4633
testStoragePoolUndefine(virStoragePoolPtr pool)
{
4634
    testDriverPtr privconn = pool->conn->privateData;
4635
    virStoragePoolObjPtr obj;
4636
    virObjectEventPtr event = NULL;
4637

4638 4639
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
4640

4641 4642 4643 4644
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_UNDEFINED,
                                            0);

4645
    virStoragePoolObjRemove(privconn->pools, obj);
4646
    virObjectUnref(obj);
C
Cole Robinson 已提交
4647

4648
    testObjectEventQueue(privconn, event);
4649
    return 0;
C
Cole Robinson 已提交
4650 4651
}

4652

C
Cole Robinson 已提交
4653
static int
4654
testStoragePoolBuild(virStoragePoolPtr pool,
E
Eric Blake 已提交
4655 4656
                     unsigned int flags)
{
4657
    testDriverPtr privconn = pool->conn->privateData;
4658
    virStoragePoolObjPtr obj;
4659
    virObjectEventPtr event = NULL;
4660

E
Eric Blake 已提交
4661 4662
    virCheckFlags(0, -1);

4663 4664
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
4665

4666 4667 4668 4669
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_CREATED,
                                            0);

4670
    virStoragePoolObjEndAPI(&obj);
4671 4672

    testObjectEventQueue(privconn, event);
4673
    return 0;
C
Cole Robinson 已提交
4674 4675 4676
}


4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691
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 */
4692 4693
    if (!(obj = virNodeDeviceObjListFindByName(privconn->devs,
                                               "scsi_host12"))) {
4694 4695
        virReportError(VIR_ERR_NO_NODE_DEVICE, "%s",
                       _("no node device with matching name 'scsi_host12'"));
4696
        return -1;
4697 4698 4699 4700 4701 4702
    }

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

4703
    virNodeDeviceObjListRemove(privconn->devs, obj);
4704
    virObjectUnref(obj);
4705 4706

    testObjectEventQueue(privconn, event);
4707
    return 0;
4708 4709 4710
}


C
Cole Robinson 已提交
4711
static int
4712 4713
testStoragePoolDestroy(virStoragePoolPtr pool)
{
4714
    testDriverPtr privconn = pool->conn->privateData;
4715
    virStoragePoolObjPtr obj;
4716
    virStoragePoolDefPtr def;
4717
    int ret = -1;
4718
    virObjectEventPtr event = NULL;
4719

4720
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
4721
        return -1;
4722
    def = virStoragePoolObjGetDef(obj);
4723

4724
    virStoragePoolObjSetActive(obj, false);
4725

4726
    if (def->source.adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
4727
        if (testDestroyVport(privconn,
4728 4729
                             def->source.adapter.data.fchost.wwnn,
                             def->source.adapter.data.fchost.wwpn) < 0)
4730 4731 4732
            goto cleanup;
    }

4733 4734
    event = virStoragePoolEventLifecycleNew(def->name,
                                            def->uuid,
4735 4736
                                            VIR_STORAGE_POOL_EVENT_STOPPED,
                                            0);
C
Cole Robinson 已提交
4737

4738
    if (!(virStoragePoolObjGetConfigFile(obj))) {
4739
        virStoragePoolObjRemove(privconn->pools, obj);
4740
        virObjectUnref(obj);
4741
        obj = NULL;
4742
    }
4743
    ret = 0;
C
Cole Robinson 已提交
4744

4745
 cleanup:
4746
    testObjectEventQueue(privconn, event);
4747
    virStoragePoolObjEndAPI(&obj);
4748
    return ret;
C
Cole Robinson 已提交
4749 4750 4751 4752
}


static int
4753
testStoragePoolDelete(virStoragePoolPtr pool,
E
Eric Blake 已提交
4754 4755
                      unsigned int flags)
{
4756
    testDriverPtr privconn = pool->conn->privateData;
4757
    virStoragePoolObjPtr obj;
4758
    virObjectEventPtr event = NULL;
4759

E
Eric Blake 已提交
4760 4761
    virCheckFlags(0, -1);

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

4765 4766 4767 4768 4769 4770
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_DELETED,
                                            0);

    testObjectEventQueue(privconn, event);

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


static int
4777
testStoragePoolRefresh(virStoragePoolPtr pool,
E
Eric Blake 已提交
4778 4779
                       unsigned int flags)
{
4780
    testDriverPtr privconn = pool->conn->privateData;
4781
    virStoragePoolObjPtr obj;
4782
    virObjectEventPtr event = NULL;
4783

E
Eric Blake 已提交
4784 4785
    virCheckFlags(0, -1);

4786 4787
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return -1;
4788

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

4791
    testObjectEventQueue(privconn, event);
4792
    virStoragePoolObjEndAPI(&obj);
4793
    return 0;
C
Cole Robinson 已提交
4794 4795 4796 4797
}


static int
4798
testStoragePoolGetInfo(virStoragePoolPtr pool,
4799 4800
                       virStoragePoolInfoPtr info)
{
4801
    testDriverPtr privconn = pool->conn->privateData;
4802
    virStoragePoolObjPtr obj;
4803
    virStoragePoolDefPtr def;
4804

4805
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
4806
        return -1;
4807
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4808 4809

    memset(info, 0, sizeof(virStoragePoolInfo));
4810
    if (virStoragePoolObjIsActive(obj))
C
Cole Robinson 已提交
4811 4812 4813
        info->state = VIR_STORAGE_POOL_RUNNING;
    else
        info->state = VIR_STORAGE_POOL_INACTIVE;
4814 4815 4816
    info->capacity = def->capacity;
    info->allocation = def->allocation;
    info->available = def->available;
C
Cole Robinson 已提交
4817

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

4822

C
Cole Robinson 已提交
4823
static char *
4824
testStoragePoolGetXMLDesc(virStoragePoolPtr pool,
E
Eric Blake 已提交
4825 4826
                          unsigned int flags)
{
4827
    testDriverPtr privconn = pool->conn->privateData;
4828
    virStoragePoolObjPtr obj;
4829
    char *ret = NULL;
4830

E
Eric Blake 已提交
4831 4832
    virCheckFlags(0, NULL);

4833
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
4834
        return NULL;
4835

4836
    ret = virStoragePoolDefFormat(virStoragePoolObjGetDef(obj));
4837

4838
    virStoragePoolObjEndAPI(&obj);
4839
    return ret;
C
Cole Robinson 已提交
4840 4841
}

4842

C
Cole Robinson 已提交
4843
static int
4844
testStoragePoolGetAutostart(virStoragePoolPtr pool,
4845 4846
                            int *autostart)
{
4847
    testDriverPtr privconn = pool->conn->privateData;
4848
    virStoragePoolObjPtr obj;
4849

4850
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
4851
        return -1;
C
Cole Robinson 已提交
4852

4853
    if (!virStoragePoolObjGetConfigFile(obj))
C
Cole Robinson 已提交
4854
        *autostart = 0;
4855
    else
4856
        *autostart = virStoragePoolObjIsAutostart(obj) ? 1 : 0;
C
Cole Robinson 已提交
4857

4858
    virStoragePoolObjEndAPI(&obj);
4859
    return 0;
C
Cole Robinson 已提交
4860 4861
}

4862

C
Cole Robinson 已提交
4863
static int
4864
testStoragePoolSetAutostart(virStoragePoolPtr pool,
4865 4866
                            int autostart)
{
4867
    testDriverPtr privconn = pool->conn->privateData;
4868
    virStoragePoolObjPtr obj;
4869
    bool new_autostart = (autostart != 0);
4870
    int ret = -1;
4871

4872
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
4873
        return -1;
C
Cole Robinson 已提交
4874

4875
    if (!virStoragePoolObjGetConfigFile(obj)) {
4876 4877
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("pool has no config file"));
4878
        goto cleanup;
C
Cole Robinson 已提交
4879 4880
    }

4881
    virStoragePoolObjSetAutostart(obj, new_autostart);
4882 4883
    ret = 0;

4884
 cleanup:
4885
    virStoragePoolObjEndAPI(&obj);
4886
    return ret;
C
Cole Robinson 已提交
4887 4888 4889 4890
}


static int
4891 4892
testStoragePoolNumOfVolumes(virStoragePoolPtr pool)
{
4893
    testDriverPtr privconn = pool->conn->privateData;
4894
    virStoragePoolObjPtr obj;
4895
    int ret = -1;
4896

4897 4898
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
4899

4900
    ret = virStoragePoolObjNumOfVolumes(obj, pool->conn, NULL);
4901

4902
    virStoragePoolObjEndAPI(&obj);
4903
    return ret;
C
Cole Robinson 已提交
4904 4905
}

4906

C
Cole Robinson 已提交
4907
static int
4908
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4909
                           char **const names,
4910 4911
                           int maxnames)
{
4912
    testDriverPtr privconn = pool->conn->privateData;
4913
    virStoragePoolObjPtr obj;
4914
    int n = -1;
4915

4916
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
4917
        return -1;
4918

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

4921
    virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
4922 4923 4924
    return n;
}

4925

4926
static int
4927
testStoragePoolListAllVolumes(virStoragePoolPtr pool,
4928
                              virStorageVolPtr **vols,
4929 4930
                              unsigned int flags)
{
4931 4932
    testDriverPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr obj;
4933 4934 4935 4936
    int ret = -1;

    virCheckFlags(0, -1);

4937
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
4938
        return -1;
4939

4940
    if (!virStoragePoolObjIsActive(obj)) {
4941 4942 4943 4944 4945
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("storage pool is not active"));
        goto cleanup;
    }

4946
    ret = virStoragePoolObjVolumeListExport(pool->conn, obj, vols, NULL);
4947 4948

 cleanup:
4949
    virStoragePoolObjEndAPI(&obj);
4950 4951 4952

    return ret;
}
C
Cole Robinson 已提交
4953

4954

4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969
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 已提交
4970
static virStorageVolPtr
4971
testStorageVolLookupByName(virStoragePoolPtr pool,
4972
                           const char *name)
4973
{
4974
    testDriverPtr privconn = pool->conn->privateData;
4975
    virStoragePoolObjPtr obj;
4976
    virStoragePoolDefPtr def;
4977
    virStorageVolDefPtr privvol;
4978
    virStorageVolPtr ret = NULL;
4979

4980 4981
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return NULL;
4982
    def = virStoragePoolObjGetDef(obj);
4983

4984
    if (!(privvol = testStorageVolDefFindByName(obj, name)))
4985
        goto cleanup;
C
Cole Robinson 已提交
4986

4987
    ret = virGetStorageVol(pool->conn, def->name,
4988 4989
                           privvol->name, privvol->key,
                           NULL, NULL);
4990

4991
 cleanup:
4992
    virStoragePoolObjEndAPI(&obj);
4993
    return ret;
C
Cole Robinson 已提交
4994 4995 4996
}


4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016
struct storageVolLookupData {
    virConnectPtr conn;
    const char *key;
    const char *path;
    virStorageVolDefPtr voldef;
};

static bool
testStorageVolLookupByKeyCallback(virStoragePoolObjPtr obj,
                                  const void *opaque)
{
    struct storageVolLookupData *data = (struct storageVolLookupData *) opaque;

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

    return !!data->voldef;
}


C
Cole Robinson 已提交
5017
static virStorageVolPtr
5018
testStorageVolLookupByKey(virConnectPtr conn,
5019 5020
                          const char *key)
{
5021
    testDriverPtr privconn = conn->privateData;
5022
    virStoragePoolObjPtr obj;
5023
    virStoragePoolDefPtr def;
5024 5025 5026
    struct storageVolLookupData data = {
        .conn = conn, .key = key, .voldef = NULL };
    virStorageVolPtr vol = NULL;
C
Cole Robinson 已提交
5027

5028
    testDriverLock(privconn);
5029
    if ((obj = virStoragePoolObjListSearch(privconn->pools,
5030 5031
                                           testStorageVolLookupByKeyCallback,
                                           &data)) && data.voldef) {
5032
        def = virStoragePoolObjGetDef(obj);
5033 5034 5035
        vol = virGetStorageVol(conn, def->name,
                               data.voldef->name, data.voldef->key,
                               NULL, NULL);
5036
        virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
5037
    }
5038
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
5039

5040
    if (!vol)
5041 5042
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching key '%s'"), key);
5043

5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057
    return vol;
}


static bool
testStorageVolLookupByPathCallback(virStoragePoolObjPtr obj,
                                   const void *opaque)
{
    struct storageVolLookupData *data = (struct storageVolLookupData *) opaque;

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

    return !!data->voldef;
C
Cole Robinson 已提交
5058 5059
}

5060

C
Cole Robinson 已提交
5061
static virStorageVolPtr
5062
testStorageVolLookupByPath(virConnectPtr conn,
5063 5064
                           const char *path)
{
5065
    testDriverPtr privconn = conn->privateData;
5066
    virStoragePoolObjPtr obj;
5067
    virStoragePoolDefPtr def;
5068 5069 5070
    struct storageVolLookupData data = {
        .conn = conn, .path = path, .voldef = NULL };
    virStorageVolPtr vol = NULL;
C
Cole Robinson 已提交
5071

5072
    testDriverLock(privconn);
5073
    if ((obj = virStoragePoolObjListSearch(privconn->pools,
5074 5075
                                           testStorageVolLookupByPathCallback,
                                           &data)) && data.voldef) {
5076
        def = virStoragePoolObjGetDef(obj);
5077 5078 5079
        vol = virGetStorageVol(conn, def->name,
                               data.voldef->name, data.voldef->key,
                               NULL, NULL);
5080
        virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
5081
    }
5082
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
5083

5084
    if (!vol)
5085 5086
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching path '%s'"), path);
5087

5088
    return vol;
C
Cole Robinson 已提交
5089 5090
}

5091

C
Cole Robinson 已提交
5092
static virStorageVolPtr
5093 5094 5095
testStorageVolCreateXML(virStoragePoolPtr pool,
                        const char *xmldesc,
                        unsigned int flags)
E
Eric Blake 已提交
5096
{
5097
    testDriverPtr privconn = pool->conn->privateData;
5098
    virStoragePoolObjPtr obj;
5099
    virStoragePoolDefPtr def;
5100 5101
    virStorageVolDefPtr privvol = NULL;
    virStorageVolPtr ret = NULL;
5102

E
Eric Blake 已提交
5103 5104
    virCheckFlags(0, NULL);

5105 5106
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return NULL;
5107
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
5108

5109
    privvol = virStorageVolDefParseString(def, xmldesc, 0);
5110
    if (privvol == NULL)
5111
        goto cleanup;
5112

5113
    if (virStorageVolDefFindByName(obj, privvol->name)) {
5114 5115
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
5116
        goto cleanup;
C
Cole Robinson 已提交
5117 5118 5119
    }

    /* Make sure enough space */
5120 5121
    if ((def->allocation + privvol->target.allocation) >
         def->capacity) {
5122 5123 5124
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
5125
        goto cleanup;
C
Cole Robinson 已提交
5126 5127
    }

5128
    if (virAsprintf(&privvol->target.path, "%s/%s",
5129
                    def->target.path, privvol->name) < 0)
5130
        goto cleanup;
C
Cole Robinson 已提交
5131

5132
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
5133
        virStoragePoolObjAddVol(obj, privvol) < 0)
5134
        goto cleanup;
C
Cole Robinson 已提交
5135

5136 5137
    def->allocation += privvol->target.allocation;
    def->available = (def->capacity - def->allocation);
C
Cole Robinson 已提交
5138

5139
    ret = virGetStorageVol(pool->conn, def->name,
5140 5141
                           privvol->name, privvol->key,
                           NULL, NULL);
5142
    privvol = NULL;
5143

5144
 cleanup:
5145
    virStorageVolDefFree(privvol);
5146
    virStoragePoolObjEndAPI(&obj);
5147
    return ret;
C
Cole Robinson 已提交
5148 5149
}

5150

5151
static virStorageVolPtr
5152 5153 5154 5155
testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
                            const char *xmldesc,
                            virStorageVolPtr clonevol,
                            unsigned int flags)
E
Eric Blake 已提交
5156
{
5157
    testDriverPtr privconn = pool->conn->privateData;
5158
    virStoragePoolObjPtr obj;
5159
    virStoragePoolDefPtr def;
5160 5161 5162
    virStorageVolDefPtr privvol = NULL, origvol = NULL;
    virStorageVolPtr ret = NULL;

E
Eric Blake 已提交
5163 5164
    virCheckFlags(0, NULL);

5165 5166
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return NULL;
5167
    def = virStoragePoolObjGetDef(obj);
5168

5169
    privvol = virStorageVolDefParseString(def, xmldesc, 0);
5170 5171 5172
    if (privvol == NULL)
        goto cleanup;

5173
    if (virStorageVolDefFindByName(obj, privvol->name)) {
5174 5175
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
5176 5177 5178
        goto cleanup;
    }

5179
    origvol = virStorageVolDefFindByName(obj, clonevol->name);
5180
    if (!origvol) {
5181 5182 5183
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       clonevol->name);
5184 5185 5186 5187
        goto cleanup;
    }

    /* Make sure enough space */
5188
    if ((def->allocation + privvol->target.allocation) > def->capacity) {
5189 5190 5191
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
5192 5193
        goto cleanup;
    }
5194
    def->available = (def->capacity - def->allocation);
5195

5196
    if (virAsprintf(&privvol->target.path, "%s/%s",
5197
                    def->target.path, privvol->name) < 0)
5198 5199
        goto cleanup;

5200
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
5201
        virStoragePoolObjAddVol(obj, privvol) < 0)
5202 5203
        goto cleanup;

5204 5205
    def->allocation += privvol->target.allocation;
    def->available = (def->capacity - def->allocation);
5206

5207
    ret = virGetStorageVol(pool->conn, def->name,
5208 5209
                           privvol->name, privvol->key,
                           NULL, NULL);
5210 5211
    privvol = NULL;

5212
 cleanup:
5213
    virStorageVolDefFree(privvol);
5214
    virStoragePoolObjEndAPI(&obj);
5215 5216 5217
    return ret;
}

5218

C
Cole Robinson 已提交
5219
static int
5220 5221
testStorageVolDelete(virStorageVolPtr vol,
                     unsigned int flags)
E
Eric Blake 已提交
5222
{
5223
    testDriverPtr privconn = vol->conn->privateData;
5224
    virStoragePoolObjPtr obj;
5225
    virStoragePoolDefPtr def;
5226
    virStorageVolDefPtr privvol;
5227
    int ret = -1;
C
Cole Robinson 已提交
5228

E
Eric Blake 已提交
5229 5230
    virCheckFlags(0, -1);

5231 5232
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return -1;
5233
    def = virStoragePoolObjGetDef(obj);
5234

5235
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
5236
        goto cleanup;
5237

5238 5239
    def->allocation -= privvol->target.allocation;
    def->available = (def->capacity - def->allocation);
C
Cole Robinson 已提交
5240

5241
    virStoragePoolObjRemoveVol(obj, privvol);
C
Cole Robinson 已提交
5242

5243
    ret = 0;
C
Cole Robinson 已提交
5244

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


5251 5252
static int
testStorageVolumeTypeForPool(int pooltype)
5253
{
C
Cole Robinson 已提交
5254

5255
    switch (pooltype) {
C
Cole Robinson 已提交
5256 5257 5258 5259 5260 5261 5262 5263 5264
        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;
    }
}

5265

C
Cole Robinson 已提交
5266
static int
5267
testStorageVolGetInfo(virStorageVolPtr vol,
5268 5269
                      virStorageVolInfoPtr info)
{
5270
    testDriverPtr privconn = vol->conn->privateData;
5271
    virStoragePoolObjPtr obj;
5272
    virStoragePoolDefPtr def;
5273
    virStorageVolDefPtr privvol;
5274
    int ret = -1;
5275

5276 5277
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return -1;
5278
    def = virStoragePoolObjGetDef(obj);
5279

5280
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
5281
        goto cleanup;
5282

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

5289
 cleanup:
5290
    virStoragePoolObjEndAPI(&obj);
5291
    return ret;
C
Cole Robinson 已提交
5292 5293
}

5294

C
Cole Robinson 已提交
5295
static char *
5296 5297
testStorageVolGetXMLDesc(virStorageVolPtr vol,
                         unsigned int flags)
E
Eric Blake 已提交
5298
{
5299
    testDriverPtr privconn = vol->conn->privateData;
5300
    virStoragePoolObjPtr obj;
5301
    virStorageVolDefPtr privvol;
5302
    char *ret = NULL;
5303

E
Eric Blake 已提交
5304 5305
    virCheckFlags(0, NULL);

5306 5307
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return NULL;
5308

5309
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
5310
        goto cleanup;
C
Cole Robinson 已提交
5311

5312
    ret = virStorageVolDefFormat(virStoragePoolObjGetDef(obj), privvol);
5313

5314
 cleanup:
5315
    virStoragePoolObjEndAPI(&obj);
5316
    return ret;
C
Cole Robinson 已提交
5317 5318
}

5319

C
Cole Robinson 已提交
5320
static char *
5321 5322
testStorageVolGetPath(virStorageVolPtr vol)
{
5323
    testDriverPtr privconn = vol->conn->privateData;
5324
    virStoragePoolObjPtr obj;
5325
    virStorageVolDefPtr privvol;
5326
    char *ret = NULL;
5327

5328 5329
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return NULL;
5330

5331
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
5332
        goto cleanup;
5333

5334
    ignore_value(VIR_STRDUP(ret, privvol->target.path));
5335

5336
 cleanup:
5337
    virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
5338 5339 5340
    return ret;
}

5341

5342
/* Node device implementations */
5343

5344 5345 5346 5347 5348 5349
static virNodeDeviceObjPtr
testNodeDeviceObjFindByName(testDriverPtr driver,
                            const char *name)
{
    virNodeDeviceObjPtr obj;

5350
    if (!(obj = virNodeDeviceObjListFindByName(driver->devs, name)))
5351 5352 5353 5354 5355 5356 5357 5358
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       name);

    return obj;
}


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

E
Eric Blake 已提交
5366 5367
    virCheckFlags(0, -1);

5368
    return virNodeDeviceObjListNumOfDevices(driver->devs, conn, cap, NULL);
5369 5370
}

5371

5372 5373 5374 5375 5376
static int
testNodeListDevices(virConnectPtr conn,
                    const char *cap,
                    char **const names,
                    int maxnames,
E
Eric Blake 已提交
5377
                    unsigned int flags)
5378
{
5379
    testDriverPtr driver = conn->privateData;
5380

E
Eric Blake 已提交
5381 5382
    virCheckFlags(0, -1);

5383 5384
    return virNodeDeviceObjListGetNames(driver->devs, conn, NULL,
                                        cap, names, maxnames);
5385 5386
}

5387

5388 5389 5390
static virNodeDevicePtr
testNodeDeviceLookupByName(virConnectPtr conn, const char *name)
{
5391
    testDriverPtr driver = conn->privateData;
5392
    virNodeDeviceObjPtr obj;
5393
    virNodeDeviceDefPtr def;
5394 5395
    virNodeDevicePtr ret = NULL;

5396
    if (!(obj = testNodeDeviceObjFindByName(driver, name)))
5397
        return NULL;
5398
    def = virNodeDeviceObjGetDef(obj);
5399

5400
    if ((ret = virGetNodeDevice(conn, name))) {
5401
        if (VIR_STRDUP(ret->parent, def->parent) < 0) {
5402
            virObjectUnref(ret);
5403 5404
            ret = NULL;
        }
5405
    }
5406

5407
    virNodeDeviceObjEndAPI(&obj);
5408 5409 5410 5411
    return ret;
}

static char *
5412
testNodeDeviceGetXMLDesc(virNodeDevicePtr dev,
E
Eric Blake 已提交
5413
                         unsigned int flags)
5414
{
5415
    testDriverPtr driver = dev->conn->privateData;
5416 5417 5418
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

E
Eric Blake 已提交
5419 5420
    virCheckFlags(0, NULL);

5421
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5422
        return NULL;
5423

5424
    ret = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(obj));
5425

5426
    virNodeDeviceObjEndAPI(&obj);
5427 5428 5429 5430 5431 5432
    return ret;
}

static char *
testNodeDeviceGetParent(virNodeDevicePtr dev)
{
5433
    testDriverPtr driver = dev->conn->privateData;
5434
    virNodeDeviceObjPtr obj;
5435
    virNodeDeviceDefPtr def;
5436 5437
    char *ret = NULL;

5438
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5439
        return NULL;
5440
    def = virNodeDeviceObjGetDef(obj);
5441

5442 5443
    if (def->parent) {
        ignore_value(VIR_STRDUP(ret, def->parent));
5444
    } else {
5445 5446
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no parent for this device"));
5447 5448
    }

5449
    virNodeDeviceObjEndAPI(&obj);
5450 5451 5452
    return ret;
}

5453

5454 5455 5456
static int
testNodeDeviceNumOfCaps(virNodeDevicePtr dev)
{
5457
    testDriverPtr driver = dev->conn->privateData;
5458
    virNodeDeviceObjPtr obj;
5459
    virNodeDeviceDefPtr def;
5460 5461 5462
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;

5463
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5464
        return -1;
5465
    def = virNodeDeviceObjGetDef(obj);
5466

5467
    for (caps = def->caps; caps; caps = caps->next)
5468 5469
        ++ncaps;

5470
    virNodeDeviceObjEndAPI(&obj);
5471
    return ncaps;
5472 5473 5474 5475 5476 5477
}


static int
testNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
5478
    testDriverPtr driver = dev->conn->privateData;
5479
    virNodeDeviceObjPtr obj;
5480
    virNodeDeviceDefPtr def;
5481 5482 5483
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;

5484
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5485
        return -1;
5486
    def = virNodeDeviceObjGetDef(obj);
5487

5488
    for (caps = def->caps; caps && ncaps < maxnames; caps = caps->next) {
5489 5490 5491 5492
        if (VIR_STRDUP(names[ncaps],
                       virNodeDevCapTypeToString(caps->data.type)) < 0)
            goto error;
        ncaps++;
5493 5494
    }

5495
    virNodeDeviceObjEndAPI(&obj);
5496 5497 5498 5499 5500
    return ncaps;

 error:
    while (--ncaps >= 0)
        VIR_FREE(names[ncaps]);
5501
    virNodeDeviceObjEndAPI(&obj);
5502
    return -1;
5503 5504
}

5505

5506 5507
static virNodeDeviceObjPtr
testNodeDeviceMockCreateVport(testDriverPtr driver,
5508
                              const char *wwnn,
5509
                              const char *wwpn)
5510
{
5511 5512
    char *xml = NULL;
    virNodeDeviceDefPtr def = NULL;
5513
    virNodeDevCapsDefPtr caps;
5514
    virNodeDeviceObjPtr obj = NULL, objcopy = NULL;
5515
    virNodeDeviceDefPtr objdef;
5516
    virObjectEventPtr event = NULL;
5517

5518 5519 5520 5521 5522 5523 5524 5525 5526
    /* 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. */
5527 5528
    if (!(objcopy = virNodeDeviceObjListFindByName(driver->devs,
                                                   "scsi_host11")))
5529 5530
        goto cleanup;

5531
    xml = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(objcopy));
5532
    virNodeDeviceObjEndAPI(&objcopy);
5533 5534 5535 5536
    if (!xml)
        goto cleanup;

    if (!(def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL)))
5537 5538
        goto cleanup;

5539
    VIR_FREE(def->name);
5540
    if (VIR_STRDUP(def->name, "scsi_host12") < 0)
5541 5542
        goto cleanup;

5543 5544 5545
    /* 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. */
5546 5547
    caps = def->caps;
    while (caps) {
5548
        if (caps->data.type != VIR_NODE_DEV_CAP_SCSI_HOST)
5549 5550
            continue;

5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564
        /* 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++;
        }
5565 5566 5567
        caps = caps->next;
    }

5568
    if (!(obj = virNodeDeviceObjListAssignDef(driver->devs, def)))
5569
        goto cleanup;
5570
    def = NULL;
5571
    objdef = virNodeDeviceObjGetDef(obj);
5572

5573
    event = virNodeDeviceEventLifecycleNew(objdef->name,
5574 5575
                                           VIR_NODE_DEVICE_EVENT_CREATED,
                                           0);
5576 5577 5578
    testObjectEventQueue(driver, event);

 cleanup:
5579
    VIR_FREE(xml);
5580 5581
    virNodeDeviceDefFree(def);
    return obj;
5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592
}


static virNodeDevicePtr
testNodeDeviceCreateXML(virConnectPtr conn,
                        const char *xmlDesc,
                        unsigned int flags)
{
    testDriverPtr driver = conn->privateData;
    virNodeDeviceDefPtr def = NULL;
    char *wwnn = NULL, *wwpn = NULL;
5593 5594
    virNodeDevicePtr dev = NULL, ret = NULL;
    virNodeDeviceObjPtr obj = NULL;
5595
    virNodeDeviceDefPtr objdef;
5596 5597 5598 5599 5600 5601

    virCheckFlags(0, NULL);

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

5602 5603 5604
    /* We run this simply for validation - it essentially validates that
     * the input XML either has a wwnn/wwpn or virNodeDevCapSCSIHostParseXML
     * generated a wwnn/wwpn */
5605 5606 5607
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) < 0)
        goto cleanup;

5608 5609 5610
    /* 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. */
5611
    if (virNodeDeviceObjListGetParentHost(driver->devs, def) < 0)
5612 5613 5614 5615
        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
5616 5617 5618
     * 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 */
5619 5620
    if (!(obj = testNodeDeviceMockCreateVport(driver, wwnn, wwpn)))
        goto cleanup;
5621
    objdef = virNodeDeviceObjGetDef(obj);
5622

5623
    if (!(dev = virGetNodeDevice(conn, objdef->name)))
5624 5625 5626 5627 5628 5629 5630 5631
        goto cleanup;

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

    ret = dev;
    dev = NULL;
5632

5633
 cleanup:
5634
    virNodeDeviceObjEndAPI(&obj);
5635
    virNodeDeviceDefFree(def);
5636
    virObjectUnref(dev);
5637 5638
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
5639
    return ret;
5640 5641 5642 5643 5644 5645
}

static int
testNodeDeviceDestroy(virNodeDevicePtr dev)
{
    int ret = 0;
5646
    testDriverPtr driver = dev->conn->privateData;
5647
    virNodeDeviceObjPtr obj = NULL;
5648
    virNodeDeviceObjPtr parentobj = NULL;
5649
    virNodeDeviceDefPtr def;
5650
    char *wwnn = NULL, *wwpn = NULL;
5651
    virObjectEventPtr event = NULL;
5652

5653
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
5654
        return -1;
5655
    def = virNodeDeviceObjGetDef(obj);
5656

5657
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) == -1)
5658
        goto cleanup;
5659

5660 5661 5662 5663
    /* 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 */
5664
    virObjectUnlock(obj);
5665

5666 5667 5668 5669 5670 5671
    /* 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);
5672
        virObjectLock(obj);
5673
        goto cleanup;
5674
    }
5675
    virNodeDeviceObjEndAPI(&parentobj);
5676

5677 5678 5679 5680
    event = virNodeDeviceEventLifecycleNew(dev->name,
                                           VIR_NODE_DEVICE_EVENT_DELETED,
                                           0);

5681
    virObjectLock(obj);
5682
    virNodeDeviceObjListRemove(driver->devs, obj);
5683
    virObjectUnref(obj);
5684
    obj = NULL;
5685

5686
 cleanup:
5687
    virNodeDeviceObjEndAPI(&obj);
5688
    testObjectEventQueue(driver, event);
5689 5690 5691 5692 5693
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return ret;
}

5694 5695

/* Domain event implementations */
5696
static int
5697 5698 5699 5700
testConnectDomainEventRegister(virConnectPtr conn,
                               virConnectDomainEventCallback callback,
                               void *opaque,
                               virFreeCallback freecb)
5701
{
5702
    testDriverPtr driver = conn->privateData;
5703
    int ret = 0;
5704

5705
    if (virDomainEventStateRegister(conn, driver->eventState,
5706 5707
                                    callback, opaque, freecb) < 0)
        ret = -1;
5708 5709 5710 5711

    return ret;
}

5712

5713
static int
5714 5715
testConnectDomainEventDeregister(virConnectPtr conn,
                                 virConnectDomainEventCallback callback)
5716
{
5717
    testDriverPtr driver = conn->privateData;
5718
    int ret = 0;
5719

5720
    if (virDomainEventStateDeregister(conn, driver->eventState,
5721 5722
                                      callback) < 0)
        ret = -1;
5723 5724 5725 5726

    return ret;
}

5727 5728

static int
5729 5730 5731 5732 5733 5734
testConnectDomainEventRegisterAny(virConnectPtr conn,
                                  virDomainPtr dom,
                                  int eventID,
                                  virConnectDomainEventGenericCallback callback,
                                  void *opaque,
                                  virFreeCallback freecb)
5735
{
5736
    testDriverPtr driver = conn->privateData;
5737 5738
    int ret;

5739
    if (virDomainEventStateRegisterID(conn, driver->eventState,
5740 5741
                                      dom, eventID,
                                      callback, opaque, freecb, &ret) < 0)
5742
        ret = -1;
5743 5744 5745 5746 5747

    return ret;
}

static int
5748 5749
testConnectDomainEventDeregisterAny(virConnectPtr conn,
                                    int callbackID)
5750
{
5751
    testDriverPtr driver = conn->privateData;
5752
    int ret = 0;
5753

5754
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5755
                                        callbackID, true) < 0)
5756
        ret = -1;
5757 5758 5759 5760 5761

    return ret;
}


5762 5763 5764 5765 5766 5767 5768 5769
static int
testConnectNetworkEventRegisterAny(virConnectPtr conn,
                                   virNetworkPtr net,
                                   int eventID,
                                   virConnectNetworkEventGenericCallback callback,
                                   void *opaque,
                                   virFreeCallback freecb)
{
5770
    testDriverPtr driver = conn->privateData;
5771 5772
    int ret;

5773
    if (virNetworkEventStateRegisterID(conn, driver->eventState,
5774
                                       net, eventID, callback,
5775 5776 5777 5778 5779 5780 5781 5782 5783 5784
                                       opaque, freecb, &ret) < 0)
        ret = -1;

    return ret;
}

static int
testConnectNetworkEventDeregisterAny(virConnectPtr conn,
                                     int callbackID)
{
5785
    testDriverPtr driver = conn->privateData;
5786
    int ret = 0;
5787

5788
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5789
                                        callbackID, true) < 0)
5790
        ret = -1;
5791 5792 5793 5794

    return ret;
}

5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821
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,
5822
                                        callbackID, true) < 0)
5823 5824 5825 5826 5827
        ret = -1;

    return ret;
}

5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854
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,
5855
                                        callbackID, true) < 0)
5856 5857 5858 5859 5860
        ret = -1;

    return ret;
}

5861 5862 5863
static int testConnectListAllDomains(virConnectPtr conn,
                                     virDomainPtr **domains,
                                     unsigned int flags)
5864
{
5865
    testDriverPtr privconn = conn->privateData;
5866

O
Osier Yang 已提交
5867
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
5868

5869 5870
    return virDomainObjListExport(privconn->domains, conn, domains,
                                  NULL, flags);
5871 5872
}

5873
static int
P
Peter Krempa 已提交
5874
testNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,
5875 5876 5877 5878 5879 5880 5881
                  unsigned char **cpumap,
                  unsigned int *online,
                  unsigned int flags)
{
    virCheckFlags(0, -1);

    if (cpumap) {
5882
        if (VIR_ALLOC_N(*cpumap, 1) < 0)
P
Peter Krempa 已提交
5883
            return -1;
5884 5885 5886 5887 5888 5889
        *cpumap[0] = 0x15;
    }

    if (online)
        *online = 3;

P
Peter Krempa 已提交
5890
    return  8;
5891 5892
}

5893 5894 5895 5896 5897 5898 5899 5900 5901 5902
static char *
testDomainScreenshot(virDomainPtr dom ATTRIBUTE_UNUSED,
                     virStreamPtr st,
                     unsigned int screen ATTRIBUTE_UNUSED,
                     unsigned int flags)
{
    char *ret = NULL;

    virCheckFlags(0, NULL);

5903
    if (VIR_STRDUP(ret, "image/png") < 0)
5904 5905
        return NULL;

D
Daniel P. Berrange 已提交
5906
    if (virFDStreamOpenFile(st, PKGDATADIR "/test-screenshot.png", 0, 0, O_RDONLY) < 0)
5907 5908 5909 5910 5911
        VIR_FREE(ret);

    return ret;
}

5912 5913
static int
testConnectGetCPUModelNames(virConnectPtr conn ATTRIBUTE_UNUSED,
J
Jiri Denemark 已提交
5914
                            const char *archName,
5915 5916 5917
                            char ***models,
                            unsigned int flags)
{
J
Jiri Denemark 已提交
5918 5919
    virArch arch;

5920
    virCheckFlags(0, -1);
J
Jiri Denemark 已提交
5921 5922 5923 5924 5925 5926 5927 5928

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

J
Jiri Denemark 已提交
5929
    return virCPUGetModels(arch, models);
5930
}
5931

C
Cole Robinson 已提交
5932 5933 5934
static int
testDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
5935
    testDriverPtr privconn = dom->conn->privateData;
C
Cole Robinson 已提交
5936
    virDomainObjPtr vm = NULL;
5937
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
5938 5939 5940 5941 5942 5943
    int ret = -1;

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

5944 5945
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959

    if (!virDomainObjIsActive(vm)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto cleanup;
    }

    if (!vm->persistent) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot do managed save for transient domain"));
        goto cleanup;
    }

    testDomainShutdownState(dom, vm, VIR_DOMAIN_SHUTOFF_SAVED);
5960
    event = virDomainEventLifecycleNewFromObj(vm,
C
Cole Robinson 已提交
5961 5962 5963 5964 5965
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
    vm->hasManagedSave = true;

    ret = 0;
5966
 cleanup:
5967
    virDomainObjEndAPI(&vm);
5968
    testObjectEventQueue(privconn, event);
C
Cole Robinson 已提交
5969 5970 5971 5972 5973 5974 5975 5976 5977

    return ret;
}


static int
testDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm;
5978
    int ret;
C
Cole Robinson 已提交
5979 5980 5981

    virCheckFlags(0, -1);

5982 5983
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5984 5985

    ret = vm->hasManagedSave;
5986

5987
    virDomainObjEndAPI(&vm);
C
Cole Robinson 已提交
5988 5989 5990 5991 5992 5993 5994 5995 5996 5997
    return ret;
}

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

    virCheckFlags(0, -1);

5998 5999
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
6000 6001

    vm->hasManagedSave = false;
6002

6003
    virDomainObjEndAPI(&vm);
6004
    return 0;
C
Cole Robinson 已提交
6005 6006 6007
}


6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041
/*
 * 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;
6042
    int n;
6043 6044 6045 6046 6047

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6048
        return -1;
6049 6050 6051

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

6052
    virDomainObjEndAPI(&vm);
6053 6054 6055 6056 6057 6058 6059 6060 6061 6062
    return n;
}

static int
testDomainSnapshotListNames(virDomainPtr domain,
                            char **names,
                            int nameslen,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6063
    int n;
6064 6065 6066 6067 6068

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6069
        return -1;
6070 6071 6072 6073

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

6074
    virDomainObjEndAPI(&vm);
6075 6076 6077 6078 6079 6080 6081 6082 6083
    return n;
}

static int
testDomainListAllSnapshots(virDomainPtr domain,
                           virDomainSnapshotPtr **snaps,
                           unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6084
    int n;
6085 6086 6087 6088 6089

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6090
        return -1;
6091 6092 6093

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

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

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

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

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

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

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

6144
 cleanup:
6145
    virDomainObjEndAPI(&vm);
6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161
    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)))
6162
        return -1;
6163 6164 6165 6166 6167 6168 6169

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

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

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

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

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

6194
 cleanup:
6195
    virDomainObjEndAPI(&vm);
6196 6197 6198 6199 6200 6201 6202 6203
    return snapshot;
}

static int
testDomainHasCurrentSnapshot(virDomainPtr domain,
                             unsigned int flags)
{
    virDomainObjPtr vm;
6204
    int ret;
6205 6206 6207 6208

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6209
        return -1;
6210 6211 6212

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

6213
    virDomainObjEndAPI(&vm);
6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227
    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)))
6228
        return NULL;
6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241

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

6242
 cleanup:
6243
    virDomainObjEndAPI(&vm);
6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256
    return parent;
}

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

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
6257
        return NULL;
6258 6259 6260 6261 6262 6263 6264 6265 6266

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

6267
 cleanup:
6268
    virDomainObjEndAPI(&vm);
6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279
    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];
6280
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6281 6282 6283 6284

    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6285
        return NULL;
6286 6287 6288 6289 6290 6291

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

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

6292
    xml = virDomainSnapshotDefFormat(uuidstr, snap->def, privconn->caps,
6293
                                     privconn->xmlopt,
6294 6295
                                     virDomainDefFormatConvertXMLFlags(flags),
                                     0);
6296

6297
 cleanup:
6298
    virDomainObjEndAPI(&vm);
6299 6300 6301 6302 6303 6304 6305 6306
    return xml;
}

static int
testDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6307
    int ret;
6308 6309 6310 6311

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6312
        return -1;
6313 6314 6315 6316

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

6317
    virDomainObjEndAPI(&vm);
6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331
    return ret;
}


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

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6332
        return -1;
6333

C
Cole Robinson 已提交
6334
    if (!testSnapObjFromSnapshot(vm, snapshot))
6335 6336 6337 6338
        goto cleanup;

    ret = 1;

6339
 cleanup:
6340
    virDomainObjEndAPI(&vm);
6341 6342 6343
    return ret;
}

6344 6345 6346 6347 6348 6349
static int
testDomainSnapshotAlignDisks(virDomainObjPtr vm,
                             virDomainSnapshotDefPtr def,
                             unsigned int flags)
{
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
E
Eric Blake 已提交
6350
    bool align_match = true;
6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378

    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)
{
6379
    testDriverPtr privconn = domain->conn->privateData;
6380 6381 6382 6383
    virDomainObjPtr vm = NULL;
    virDomainSnapshotDefPtr def = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr snapshot = NULL;
6384
    virObjectEventPtr event = NULL;
6385
    char *xml = NULL;
6386 6387
    bool update_current = true;
    bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
6388 6389 6390 6391 6392 6393 6394 6395
    unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;

    /*
     * DISK_ONLY: Not implemented yet
     * REUSE_EXT: Not implemented yet
     *
     * NO_METADATA: Explicitly not implemented
     *
6396
     * REDEFINE + CURRENT: Implemented
6397 6398 6399 6400 6401 6402
     * HALT: Implemented
     * QUIESCE: Nothing to do
     * ATOMIC: Nothing to do
     * LIVE: Nothing to do
     */
    virCheckFlags(
6403 6404
        VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
        VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
6405 6406 6407 6408 6409
        VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
        VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
        VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
        VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, NULL);

6410 6411 6412 6413 6414
    if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)))
        update_current = false;
    if (redefine)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;

6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429
    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;

6430
    if (redefine) {
C
Cole Robinson 已提交
6431
        if (virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
6432
                                          privconn->xmlopt,
C
Cole Robinson 已提交
6433
                                          &update_current, flags) < 0)
6434 6435 6436 6437 6438
            goto cleanup;
    } else {
        if (!(def->dom = virDomainDefCopy(vm->def,
                                          privconn->caps,
                                          privconn->xmlopt,
6439
                                          NULL,
6440 6441
                                          true)))
            goto cleanup;
6442

6443
        if (testDomainSnapshotAlignDisks(vm, def, flags) < 0)
6444 6445 6446
            goto cleanup;
    }

6447 6448 6449 6450
    if (!snap) {
        if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
            goto cleanup;
        def = NULL;
6451 6452
    }

6453 6454 6455 6456 6457 6458 6459 6460 6461 6462
    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);
6463
            event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
6464 6465 6466
                                    VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
        }
    }
6467 6468

    snapshot = virGetDomainSnapshot(domain, snap->def->name);
6469
 cleanup:
6470 6471 6472 6473
    VIR_FREE(xml);
    if (vm) {
        if (snapshot) {
            virDomainSnapshotObjPtr other;
6474 6475
            if (update_current)
                vm->current_snapshot = snap;
6476 6477 6478 6479 6480 6481 6482
            other = virDomainSnapshotFindByName(vm->snapshots,
                                                snap->def->parent);
            snap->parent = other;
            other->nchildren++;
            snap->sibling = other->first_child;
            other->first_child = snap;
        }
6483
        virDomainObjEndAPI(&vm);
6484
    }
6485
    testObjectEventQueue(privconn, event);
6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497
    virDomainSnapshotDefFree(def);
    return snapshot;
}


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

6498
static int
6499
testDomainSnapshotDiscardAll(void *payload,
6500 6501
                             const void *name ATTRIBUTE_UNUSED,
                             void *data)
6502 6503 6504 6505 6506 6507 6508
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapRemoveDataPtr curr = data;

    if (snap->def->current)
        curr->current = true;
    virDomainSnapshotObjListRemove(curr->vm->snapshots, snap);
6509
    return 0;
6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520
}

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

6521
static int
6522 6523 6524 6525 6526 6527 6528
testDomainSnapshotReparentChildren(void *payload,
                                   const void *name ATTRIBUTE_UNUSED,
                                   void *data)
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapReparentDataPtr rep = data;

6529
    if (rep->err < 0)
6530
        return 0;
6531 6532 6533 6534 6535 6536 6537

    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;
6538
        return 0;
6539 6540 6541 6542
    }

    if (!snap->sibling)
        rep->last = snap;
6543
    return 0;
6544 6545 6546 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
}

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) {
6573
            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)
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 6610 6611 6612 6613 6614 6615 6616
                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;
6617
 cleanup:
6618
    virDomainObjEndAPI(&vm);
6619 6620 6621 6622 6623 6624 6625
    return ret;
}

static int
testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                           unsigned int flags)
{
6626
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6627 6628
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
6629 6630
    virObjectEventPtr event = NULL;
    virObjectEventPtr event2 = NULL;
6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693
    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;
6694 6695
    config = virDomainDefCopy(snap->def->dom, privconn->caps,
                              privconn->xmlopt, NULL, true);
6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707
    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.  */
6708 6709
            if (!virDomainDefCheckABIStability(vm->def, config,
                                               privconn->xmlopt)) {
6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722
                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);
6723
                event = virDomainEventLifecycleNewFromObj(vm,
6724 6725
                            VIR_DOMAIN_EVENT_STOPPED,
                            VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
6726
                testObjectEventQueue(privconn, event);
6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737
                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. */
6738
                event = virDomainEventLifecycleNewFromObj(vm,
6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751
                                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;
6752
            event = virDomainEventLifecycleNewFromObj(vm,
6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765
                                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 */
6766
                event2 = virDomainEventLifecycleNewFromObj(vm,
6767 6768 6769 6770 6771
                                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 已提交
6772
            virObjectUnref(event);
6773 6774 6775 6776
            event = NULL;

            if (was_stopped) {
                /* Transition 2 */
6777
                event = virDomainEventLifecycleNewFromObj(vm,
6778 6779 6780 6781
                                VIR_DOMAIN_EVENT_STARTED,
                                VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            } else if (was_running) {
                /* Transition 8 */
6782
                event = virDomainEventLifecycleNewFromObj(vm,
6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794
                                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);
6795
            event = virDomainEventLifecycleNewFromObj(vm,
6796 6797 6798 6799 6800 6801 6802 6803 6804
                                    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;

6805
            testObjectEventQueue(privconn, event);
6806
            event = virDomainEventLifecycleNewFromObj(vm,
6807 6808 6809
                            VIR_DOMAIN_EVENT_STARTED,
                            VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            if (paused) {
6810
                event2 = virDomainEventLifecycleNewFromObj(vm,
6811 6812 6813 6814 6815 6816 6817 6818
                                VIR_DOMAIN_EVENT_SUSPENDED,
                                VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
            }
        }
    }

    vm->current_snapshot = snap;
    ret = 0;
6819
 cleanup:
6820
    if (event) {
6821
        testObjectEventQueue(privconn, event);
6822
        testObjectEventQueue(privconn, event2);
C
Cole Robinson 已提交
6823
    } else {
C
Cédric Bosdonnat 已提交
6824
        virObjectUnref(event2);
6825
    }
6826
    virDomainObjEndAPI(&vm);
6827 6828 6829 6830 6831

    return ret;
}


6832

6833
static virHypervisorDriver testHypervisorDriver = {
6834
    .name = "Test",
6835 6836 6837
    .connectOpen = testConnectOpen, /* 0.1.1 */
    .connectClose = testConnectClose, /* 0.1.1 */
    .connectGetVersion = testConnectGetVersion, /* 0.1.1 */
6838
    .connectGetHostname = testConnectGetHostname, /* 0.6.3 */
6839
    .connectGetMaxVcpus = testConnectGetMaxVcpus, /* 0.3.2 */
6840
    .nodeGetInfo = testNodeGetInfo, /* 0.1.1 */
6841
    .nodeGetCPUStats = testNodeGetCPUStats, /* 2.3.0 */
6842
    .nodeGetFreeMemory = testNodeGetFreeMemory, /* 2.3.0 */
6843
    .nodeGetFreePages = testNodeGetFreePages, /* 2.3.0 */
6844
    .connectGetCapabilities = testConnectGetCapabilities, /* 0.2.1 */
6845
    .connectGetSysinfo = testConnectGetSysinfo, /* 2.3.0 */
6846
    .connectGetType = testConnectGetType, /* 2.3.0 */
6847 6848 6849
    .connectListDomains = testConnectListDomains, /* 0.1.1 */
    .connectNumOfDomains = testConnectNumOfDomains, /* 0.1.1 */
    .connectListAllDomains = testConnectListAllDomains, /* 0.9.13 */
6850
    .domainCreateXML = testDomainCreateXML, /* 0.1.4 */
6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864
    .domainLookupByID = testDomainLookupByID, /* 0.1.1 */
    .domainLookupByUUID = testDomainLookupByUUID, /* 0.1.1 */
    .domainLookupByName = testDomainLookupByName, /* 0.1.1 */
    .domainSuspend = testDomainSuspend, /* 0.1.1 */
    .domainResume = testDomainResume, /* 0.1.1 */
    .domainShutdown = testDomainShutdown, /* 0.1.1 */
    .domainShutdownFlags = testDomainShutdownFlags, /* 0.9.10 */
    .domainReboot = testDomainReboot, /* 0.1.1 */
    .domainDestroy = testDomainDestroy, /* 0.1.1 */
    .domainGetOSType = testDomainGetOSType, /* 0.1.9 */
    .domainGetMaxMemory = testDomainGetMaxMemory, /* 0.1.4 */
    .domainSetMaxMemory = testDomainSetMaxMemory, /* 0.1.1 */
    .domainSetMemory = testDomainSetMemory, /* 0.1.4 */
    .domainGetInfo = testDomainGetInfo, /* 0.1.1 */
6865 6866
    .domainGetState = testDomainGetState, /* 0.9.2 */
    .domainSave = testDomainSave, /* 0.3.2 */
6867
    .domainSaveFlags = testDomainSaveFlags, /* 0.9.4 */
6868
    .domainRestore = testDomainRestore, /* 0.3.2 */
6869
    .domainRestoreFlags = testDomainRestoreFlags, /* 0.9.4 */
6870
    .domainCoreDump = testDomainCoreDump, /* 0.3.2 */
6871
    .domainCoreDumpWithFormat = testDomainCoreDumpWithFormat, /* 1.2.3 */
6872
    .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */
6873 6874 6875 6876
    .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */
    .domainGetVcpusFlags = testDomainGetVcpusFlags, /* 0.8.5 */
    .domainPinVcpu = testDomainPinVcpu, /* 0.7.3 */
    .domainGetVcpus = testDomainGetVcpus, /* 0.7.3 */
6877
    .domainGetVcpuPinInfo = testDomainGetVcpuPinInfo, /* 1.2.18 */
6878 6879
    .domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
    .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
6880 6881
    .connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
    .connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
6882 6883 6884
    .domainCreate = testDomainCreate, /* 0.1.11 */
    .domainCreateWithFlags = testDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = testDomainDefineXML, /* 0.1.11 */
6885
    .domainDefineXMLFlags = testDomainDefineXMLFlags, /* 1.2.12 */
6886
    .domainUndefine = testDomainUndefine, /* 0.1.11 */
6887
    .domainUndefineFlags = testDomainUndefineFlags, /* 0.9.4 */
6888 6889 6890
    .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
    .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
    .domainGetSchedulerType = testDomainGetSchedulerType, /* 0.3.2 */
6891 6892 6893 6894
    .domainGetSchedulerParameters = testDomainGetSchedulerParameters, /* 0.3.2 */
    .domainGetSchedulerParametersFlags = testDomainGetSchedulerParametersFlags, /* 0.9.2 */
    .domainSetSchedulerParameters = testDomainSetSchedulerParameters, /* 0.3.2 */
    .domainSetSchedulerParametersFlags = testDomainSetSchedulerParametersFlags, /* 0.9.2 */
6895 6896 6897
    .domainBlockStats = testDomainBlockStats, /* 0.7.0 */
    .domainInterfaceStats = testDomainInterfaceStats, /* 0.7.0 */
    .nodeGetCellsFreeMemory = testNodeGetCellsFreeMemory, /* 0.4.2 */
6898 6899 6900 6901
    .connectDomainEventRegister = testConnectDomainEventRegister, /* 0.6.0 */
    .connectDomainEventDeregister = testConnectDomainEventDeregister, /* 0.6.0 */
    .connectIsEncrypted = testConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = testConnectIsSecure, /* 0.7.3 */
6902 6903 6904
    .domainIsActive = testDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = testDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = testDomainIsUpdated, /* 0.8.6 */
6905 6906 6907
    .connectDomainEventRegisterAny = testConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = testConnectDomainEventDeregisterAny, /* 0.8.0 */
    .connectIsAlive = testConnectIsAlive, /* 0.9.8 */
6908
    .nodeGetCPUMap = testNodeGetCPUMap, /* 1.0.0 */
6909
    .domainRename = testDomainRename, /* 4.1.0 */
6910
    .domainScreenshot = testDomainScreenshot, /* 1.0.5 */
6911 6912
    .domainGetMetadata = testDomainGetMetadata, /* 1.1.3 */
    .domainSetMetadata = testDomainSetMetadata, /* 1.1.3 */
6913
    .connectGetCPUModelNames = testConnectGetCPUModelNames, /* 1.1.3 */
6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930
    .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 */
6931 6932 6933
    .domainSnapshotCreateXML = testDomainSnapshotCreateXML, /* 1.1.4 */
    .domainRevertToSnapshot = testDomainRevertToSnapshot, /* 1.1.4 */
    .domainSnapshotDelete = testDomainSnapshotDelete, /* 1.1.4 */
6934

E
Eric Blake 已提交
6935
    .connectBaselineCPU = testConnectBaselineCPU, /* 1.2.0 */
6936 6937 6938
};

static virNetworkDriver testNetworkDriver = {
6939 6940 6941 6942 6943
    .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 */
6944 6945
    .connectNetworkEventRegisterAny = testConnectNetworkEventRegisterAny, /* 1.2.1 */
    .connectNetworkEventDeregisterAny = testConnectNetworkEventDeregisterAny, /* 1.2.1 */
6946 6947 6948 6949
    .networkLookupByUUID = testNetworkLookupByUUID, /* 0.3.2 */
    .networkLookupByName = testNetworkLookupByName, /* 0.3.2 */
    .networkCreateXML = testNetworkCreateXML, /* 0.3.2 */
    .networkDefineXML = testNetworkDefineXML, /* 0.3.2 */
6950
    .networkUndefine = testNetworkUndefine, /* 0.3.2 */
6951
    .networkUpdate = testNetworkUpdate, /* 0.10.2 */
6952
    .networkCreate = testNetworkCreate, /* 0.3.2 */
6953 6954 6955 6956 6957 6958 6959
    .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 */
6960 6961
};

L
Laine Stump 已提交
6962
static virInterfaceDriver testInterfaceDriver = {
6963 6964 6965 6966 6967 6968
    .connectNumOfInterfaces = testConnectNumOfInterfaces, /* 0.7.0 */
    .connectListInterfaces = testConnectListInterfaces, /* 0.7.0 */
    .connectNumOfDefinedInterfaces = testConnectNumOfDefinedInterfaces, /* 0.7.0 */
    .connectListDefinedInterfaces = testConnectListDefinedInterfaces, /* 0.7.0 */
    .interfaceLookupByName = testInterfaceLookupByName, /* 0.7.0 */
    .interfaceLookupByMACString = testInterfaceLookupByMACString, /* 0.7.0 */
6969 6970 6971 6972 6973 6974
    .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 */
6975 6976 6977
    .interfaceChangeBegin = testInterfaceChangeBegin,   /* 0.9.2 */
    .interfaceChangeCommit = testInterfaceChangeCommit,  /* 0.9.2 */
    .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */
L
Laine Stump 已提交
6978 6979 6980
};


6981
static virStorageDriver testStorageDriver = {
6982 6983 6984 6985 6986 6987
    .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 */
6988 6989
    .connectStoragePoolEventRegisterAny = testConnectStoragePoolEventRegisterAny, /* 2.0.0 */
    .connectStoragePoolEventDeregisterAny = testConnectStoragePoolEventDeregisterAny, /* 2.0.0 */
6990 6991 6992
    .storagePoolLookupByName = testStoragePoolLookupByName, /* 0.5.0 */
    .storagePoolLookupByUUID = testStoragePoolLookupByUUID, /* 0.5.0 */
    .storagePoolLookupByVolume = testStoragePoolLookupByVolume, /* 0.5.0 */
6993 6994
    .storagePoolCreateXML = testStoragePoolCreateXML, /* 0.5.0 */
    .storagePoolDefineXML = testStoragePoolDefineXML, /* 0.5.0 */
6995 6996
    .storagePoolBuild = testStoragePoolBuild, /* 0.5.0 */
    .storagePoolUndefine = testStoragePoolUndefine, /* 0.5.0 */
6997
    .storagePoolCreate = testStoragePoolCreate, /* 0.5.0 */
6998 6999 7000 7001 7002 7003 7004
    .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 */
7005
    .storagePoolNumOfVolumes = testStoragePoolNumOfVolumes, /* 0.5.0 */
7006 7007 7008
    .storagePoolListVolumes = testStoragePoolListVolumes, /* 0.5.0 */
    .storagePoolListAllVolumes = testStoragePoolListAllVolumes, /* 0.10.2 */

7009 7010 7011 7012 7013 7014 7015 7016 7017
    .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 */
7018 7019
    .storagePoolIsActive = testStoragePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = testStoragePoolIsPersistent, /* 0.7.3 */
7020 7021
};

7022
static virNodeDeviceDriver testNodeDeviceDriver = {
7023 7024
    .connectNodeDeviceEventRegisterAny = testConnectNodeDeviceEventRegisterAny, /* 2.2.0 */
    .connectNodeDeviceEventDeregisterAny = testConnectNodeDeviceEventDeregisterAny, /* 2.2.0 */
7025 7026 7027 7028 7029 7030 7031 7032 7033
    .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 */
7034 7035
};

7036 7037 7038 7039 7040 7041 7042 7043
static virConnectDriver testConnectDriver = {
    .hypervisorDriver = &testHypervisorDriver,
    .interfaceDriver = &testInterfaceDriver,
    .networkDriver = &testNetworkDriver,
    .nodeDeviceDriver = &testNodeDeviceDriver,
    .nwfilterDriver = NULL,
    .secretDriver = NULL,
    .storageDriver = &testStorageDriver,
7044 7045
};

7046 7047 7048 7049 7050 7051 7052 7053
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
7054 7055
    return virRegisterConnectDriver(&testConnectDriver,
                                    false);
7056
}