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

24
#include <config.h>
25

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

35

36
#include "virerror.h"
37
#include "datatypes.h"
38
#include "test_driver.h"
39
#include "virbuffer.h"
40
#include "viruuid.h"
41
#include "capabilities.h"
42
#include "configmake.h"
43
#include "viralloc.h"
44
#include "network_conf.h"
L
Laine Stump 已提交
45
#include "interface_conf.h"
46
#include "domain_conf.h"
47
#include "domain_event.h"
48
#include "network_event.h"
49
#include "snapshot_conf.h"
50
#include "fdstream.h"
C
Cole Robinson 已提交
51
#include "storage_conf.h"
52
#include "node_device_conf.h"
53
#include "virxml.h"
54
#include "virthread.h"
55
#include "virlog.h"
E
Eric Blake 已提交
56
#include "virfile.h"
57
#include "virtypedparam.h"
58
#include "virrandom.h"
59
#include "virstring.h"
60
#include "cpu/cpu.h"
61
#include "virauth.h"
62
#include "viratomic.h"
63
#include "virdomainobjlist.h"
64

65 66
#define VIR_FROM_THIS VIR_FROM_TEST

67 68
VIR_LOG_INIT("test.test_driver");

69

70 71 72 73 74
#define MAX_CPUS 128

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

#define MAX_CELLS 128
81

82 83 84 85 86 87 88
struct _testAuth {
    char *username;
    char *password;
};
typedef struct _testAuth testAuth;
typedef struct _testAuth *testAuthPtr;

89
struct _testDriver {
90
    virMutex lock;
91

92
    virNodeInfo nodeInfo;
L
Laine Stump 已提交
93
    virInterfaceObjList ifaces;
94 95
    bool transaction_running;
    virInterfaceObjList backupIfaces;
C
Cole Robinson 已提交
96
    virStoragePoolObjList pools;
97
    virNodeDeviceObjList devs;
98 99
    int numCells;
    testCell cells[MAX_CELLS];
100 101
    size_t numAuths;
    testAuthPtr auths;
102

103 104 105
    /* virAtomic access only */
    volatile int nextDomID;

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

121
static testDriverPtr defaultConn;
122
static int defaultConnections;
123
static virMutex defaultLock = VIR_MUTEX_INITIALIZER;
124

125
#define TEST_MODEL "i686"
126
#define TEST_EMULATOR "/usr/bin/test-hv"
127

128
static const virNodeInfo defaultNodeInfo = {
129
    TEST_MODEL,
130 131 132 133 134 135 136
    1024*1024*3, /* 3 GB */
    16,
    1400,
    2,
    2,
    2,
    2,
137 138
};

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

    virObjectUnref(driver->caps);
    virObjectUnref(driver->xmlopt);
    virObjectUnref(driver->domains);
    virNodeDeviceObjListFree(&driver->devs);
    virObjectUnref(driver->networks);
    virInterfaceObjListFree(&driver->ifaces);
    virStoragePoolObjListFree(&driver->pools);
    virObjectEventStateFree(driver->eventState);
    virMutexUnlock(&driver->lock);
    virMutexDestroy(&driver->lock);

    VIR_FREE(driver);
}
158

159

160
static void testDriverLock(testDriverPtr driver)
161
{
162
    virMutexLock(&driver->lock);
163 164
}

165
static void testDriverUnlock(testDriverPtr driver)
166
{
167
    virMutexUnlock(&driver->lock);
168 169
}

170 171 172 173 174 175 176 177 178
static void testObjectEventQueue(testDriverPtr driver,
                                 virObjectEventPtr event)
{
    if (!event)
        return;

    virObjectEventStateQueue(driver->eventState, event);
}

179 180 181 182 183 184
#define TEST_NAMESPACE_HREF "http://libvirt.org/schemas/domain/test/1.0"

typedef struct _testDomainNamespaceDef testDomainNamespaceDef;
typedef testDomainNamespaceDef *testDomainNamespaceDefPtr;
struct _testDomainNamespaceDef {
    int runstate;
185
    bool transient;
C
Cole Robinson 已提交
186
    bool hasManagedSave;
187 188 189

    unsigned int num_snap_nodes;
    xmlNodePtr *snap_nodes;
190 191 192 193 194 195
};

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

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

231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
    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);

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

264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
    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;
    }

280 281 282 283 284
    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 已提交
285 286 287 288 289
    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;
    }
290

291 292 293
    *data = nsdata;
    return 0;

294
 error:
295
    VIR_FREE(nodes);
296 297 298
    testDomainDefNamespaceFree(nsdata);
    return -1;
}
299

300
static virCapsPtr
301 302
testBuildCapabilities(virConnectPtr conn)
{
303
    testDriverPtr privconn = conn->privateData;
304 305
    virCapsPtr caps;
    virCapsGuestPtr guest;
306 307
    int guest_types[] = { VIR_DOMAIN_OSTYPE_HVM,
                          VIR_DOMAIN_OSTYPE_XEN };
308
    size_t i;
309

310
    if ((caps = virCapabilitiesNew(VIR_ARCH_I686, false, false)) == NULL)
311
        goto error;
312

313
    if (virCapabilitiesAddHostFeature(caps, "pae") < 0)
314
        goto error;
315
    if (virCapabilitiesAddHostFeature(caps, "nonpae") < 0)
316
        goto error;
317

318
    for (i = 0; i < privconn->numCells; i++) {
319 320 321
        virCapsHostNUMACellCPUPtr cpu_cells;

        if (VIR_ALLOC_N(cpu_cells, privconn->cells[i].numCpus) < 0)
322
            goto error;
323 324 325 326 327

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


328 329
        if (virCapabilitiesAddHostNUMACell(caps, i, 0,
                                           privconn->cells[i].numCpus,
M
Michal Privoznik 已提交
330
                                           cpu_cells, 0, NULL, 0, NULL) < 0)
331
            goto error;
332 333
    }

334
    for (i = 0; i < ARRAY_CARDINALITY(guest_types); i++) {
335 336
        if ((guest = virCapabilitiesAddGuest(caps,
                                             guest_types[i],
337
                                             VIR_ARCH_I686,
338 339 340 341
                                             TEST_EMULATOR,
                                             NULL,
                                             0,
                                             NULL)) == NULL)
342
            goto error;
343

344
        if (virCapabilitiesAddGuestDomain(guest,
345
                                          VIR_DOMAIN_VIRT_TEST,
346 347 348 349
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
350
            goto error;
351

352
        if (virCapabilitiesAddGuestFeature(guest, "pae", true, true) == NULL)
353
            goto error;
354
        if (virCapabilitiesAddGuestFeature(guest, "nonpae", true, true) == NULL)
355
            goto error;
356 357
    }

358 359
    caps->host.nsecModels = 1;
    if (VIR_ALLOC_N(caps->host.secModels, caps->host.nsecModels) < 0)
360
        goto error;
361 362
    if (VIR_STRDUP(caps->host.secModels[0].model, "testSecurity") < 0)
        goto error;
363

364 365
    if (VIR_STRDUP(caps->host.secModels[0].doi, "") < 0)
        goto error;
366

367
    return caps;
368

369
 error:
370
    virObjectUnref(caps);
371
    return NULL;
372 373
}

374

375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
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;
    }

393
    if (!(ret->xmlopt = virDomainXMLOptionNew(NULL, NULL, &ns)) ||
394 395 396 397 398
        !(ret->eventState = virObjectEventStateNew()) ||
        !(ret->domains = virDomainObjListNew()) ||
        !(ret->networks = virNetworkObjListNew()))
        goto error;

399
    virAtomicIntSet(&ret->nextDomID, 1);
400 401 402 403 404 405 406 407 408

    return ret;

 error:
    testDriverFree(ret);
    return NULL;
}


409 410 411
static const char *defaultDomainXML =
"<domain type='test'>"
"  <name>test</name>"
412
"  <uuid>6695eb01-f6a4-8304-79aa-97f2502e193f</uuid>"
413 414 415 416 417 418 419
"  <memory>8388608</memory>"
"  <currentMemory>2097152</currentMemory>"
"  <vcpu>2</vcpu>"
"  <os>"
"    <type>hvm</type>"
"  </os>"
"</domain>";
420 421


422 423 424
static const char *defaultNetworkXML =
"<network>"
"  <name>default</name>"
425
"  <uuid>dd8fe884-6c02-601e-7551-cca97df1c5df</uuid>"
426
"  <bridge name='virbr0'/>"
427 428 429
"  <forward/>"
"  <ip address='192.168.122.1' netmask='255.255.255.0'>"
"    <dhcp>"
430
"      <range start='192.168.122.2' end='192.168.122.254'/>"
431 432 433
"    </dhcp>"
"  </ip>"
"</network>";
434

L
Laine Stump 已提交
435 436 437 438 439 440 441 442 443 444 445
static const char *defaultInterfaceXML =
"<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>"
"</interface>";

C
Cole Robinson 已提交
446 447 448
static const char *defaultPoolXML =
"<pool type='dir'>"
"  <name>default-pool</name>"
449
"  <uuid>dfe224cb-28fb-8dd0-c4b2-64eb3f0f4566</uuid>"
C
Cole Robinson 已提交
450 451 452 453 454
"  <target>"
"    <path>/default-pool</path>"
"  </target>"
"</pool>";

455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
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";

478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
static const char *defaultNodeXML =
"<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>";

496
static const unsigned long long defaultPoolCap = (100 * 1024 * 1024 * 1024ull);
497
static const unsigned long long defaultPoolAlloc;
C
Cole Robinson 已提交
498

499
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool);
500
static int testNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
501

502 503 504 505
static virDomainObjPtr
testDomObjFromDomain(virDomainPtr domain)
{
    virDomainObjPtr vm;
506
    testDriverPtr driver = domain->conn->privateData;
507 508
    char uuidstr[VIR_UUID_STRING_BUFLEN];

509
    vm = virDomainObjListFindByUUIDRef(driver->domains, domain->uuid);
510 511 512 513 514 515 516 517 518 519
    if (!vm) {
        virUUIDFormat(domain->uuid, uuidstr);
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching uuid '%s' (%s)"),
                       uuidstr, domain->name);
    }

    return vm;
}

520
static char *
521 522
testDomainGenerateIfname(virDomainDefPtr domdef)
{
523
    int maxif = 1024;
524 525
    int ifctr;
    size_t i;
526 527 528 529 530

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

531
        if (virAsprintf(&ifname, "testnet%d", ifctr) < 0)
532 533 534
            return NULL;

        /* Generate network interface names */
535
        for (i = 0; i < domdef->nnets; i++) {
536
            if (domdef->nets[i]->ifname &&
537
                STREQ(domdef->nets[i]->ifname, ifname)) {
538 539 540 541 542 543 544
                found = 1;
                break;
            }
        }

        if (!found)
            return ifname;
545
        VIR_FREE(ifname);
546 547
    }

548 549
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Exceeded max iface limit %d"), maxif);
550 551 552
    return NULL;
}

553
static int
554
testDomainGenerateIfnames(virDomainDefPtr domdef)
555
{
556
    size_t i = 0;
557 558 559 560 561 562

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

563
        ifname = testDomainGenerateIfname(domdef);
564
        if (!ifname)
565
            return -1;
566 567 568 569

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

570
    return 0;
571 572
}

573

574 575
static void
testDomainShutdownState(virDomainPtr domain,
J
Jiri Denemark 已提交
576 577
                        virDomainObjPtr privdom,
                        virDomainShutoffReason reason)
578 579 580 581 582 583 584
{
    if (privdom->newDef) {
        virDomainDefFree(privdom->def);
        privdom->def = privdom->newDef;
        privdom->newDef = NULL;
    }

J
Jiri Denemark 已提交
585
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF, reason);
586 587 588 589 590
    privdom->def->id = -1;
    if (domain)
        domain->id = -1;
}

591
/* Set up domain runtime state */
592
static int
593
testDomainStartState(testDriverPtr privconn,
J
Jiri Denemark 已提交
594 595
                     virDomainObjPtr dom,
                     virDomainRunningReason reason)
596
{
597
    int ret = -1;
598

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

602
    if (virDomainObjSetDefTransient(privconn->caps,
603
                                    privconn->xmlopt,
604
                                    dom) < 0) {
605 606 607
        goto cleanup;
    }

C
Cole Robinson 已提交
608
    dom->hasManagedSave = false;
609
    ret = 0;
610
 cleanup:
611
    if (ret < 0)
J
Jiri Denemark 已提交
612
        testDomainShutdownState(NULL, dom, VIR_DOMAIN_SHUTOFF_FAILED);
613
    return ret;
614
}
615

616 617 618 619 620 621 622

/* 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)
{
623
    int u;
624
    testDriverPtr privconn = NULL;
625 626 627 628
    virDomainDefPtr domdef = NULL;
    virDomainObjPtr domobj = NULL;
    virNetworkDefPtr netdef = NULL;
    virNetworkObjPtr netobj = NULL;
L
Laine Stump 已提交
629 630
    virInterfaceDefPtr interfacedef = NULL;
    virInterfaceObjPtr interfaceobj = NULL;
C
Cole Robinson 已提交
631 632
    virStoragePoolDefPtr pooldef = NULL;
    virStoragePoolObjPtr poolobj = NULL;
633 634
    virNodeDeviceDefPtr nodedef = NULL;
    virNodeDeviceObjPtr nodeobj = NULL;
635

636 637
    virMutexLock(&defaultLock);
    if (defaultConnections++) {
638
        conn->privateData = defaultConn;
639 640 641 642
        virMutexUnlock(&defaultLock);
        return VIR_DRV_OPEN_SUCCESS;
    }

643
    if (!(privconn = testDriverNew()))
644
        goto error;
645 646

    conn->privateData = privconn;
647

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

650
    /* Numa setup */
651 652 653 654 655
    privconn->numCells = 2;
    for (u = 0; u < 2; ++u) {
        privconn->cells[u].numCpus = 8;
        privconn->cells[u].mem = (u + 1) * 2048 * 1024;
    }
656
    for (u = 0; u < 16; u++) {
657
        virBitmapPtr siblings = virBitmapNew(16);
658
        if (!siblings)
659 660 661 662 663 664
            goto error;
        ignore_value(virBitmapSetBit(siblings, u));
        privconn->cells[u / 8].cpus[(u % 8)].id = u;
        privconn->cells[u / 8].cpus[(u % 8)].socket_id = u / 8;
        privconn->cells[u / 8].cpus[(u % 8)].core_id = u % 8;
        privconn->cells[u / 8].cpus[(u % 8)].siblings = siblings;
665 666
    }

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

670 671
    if (!(domdef = virDomainDefParseString(defaultDomainXML,
                                           privconn->caps,
672
                                           privconn->xmlopt,
673
                                           VIR_DOMAIN_DEF_PARSE_INACTIVE)))
674
        goto error;
M
Matthias Bolte 已提交
675

676
    if (testDomainGenerateIfnames(domdef) < 0)
677
        goto error;
678
    if (!(domobj = virDomainObjListAdd(privconn->domains,
679
                                       domdef,
680
                                       privconn->xmlopt,
681
                                       0, NULL)))
682 683
        goto error;
    domdef = NULL;
684

685
    domobj->persistent = 1;
686 687
    if (testDomainStartState(privconn, domobj,
                             VIR_DOMAIN_RUNNING_BOOTED) < 0) {
688
        virObjectUnlock(domobj);
689 690 691
        goto error;
    }

692
    virObjectUnlock(domobj);
693

694
    if (!(netdef = virNetworkDefParseString(defaultNetworkXML)))
695
        goto error;
696
    if (!(netobj = virNetworkAssignDef(privconn->networks, netdef, 0))) {
697 698 699 700
        virNetworkDefFree(netdef);
        goto error;
    }
    netobj->active = 1;
701
    virNetworkObjEndAPI(&netobj);
702

703
    if (!(interfacedef = virInterfaceDefParseString(defaultInterfaceXML)))
L
Laine Stump 已提交
704
        goto error;
705
    if (!(interfaceobj = virInterfaceAssignDef(&privconn->ifaces, interfacedef))) {
L
Laine Stump 已提交
706 707 708 709 710 711
        virInterfaceDefFree(interfacedef);
        goto error;
    }
    interfaceobj->active = 1;
    virInterfaceObjUnlock(interfaceobj);

712
    if (!(pooldef = virStoragePoolDefParseString(defaultPoolXML)))
C
Cole Robinson 已提交
713 714
        goto error;

715
    if (!(poolobj = virStoragePoolObjAssignDef(&privconn->pools,
C
Cole Robinson 已提交
716 717 718 719
                                               pooldef))) {
        virStoragePoolDefFree(pooldef);
        goto error;
    }
720

721
    if (testStoragePoolObjSetDefaults(poolobj) == -1) {
722
        virStoragePoolObjUnlock(poolobj);
C
Cole Robinson 已提交
723
        goto error;
724
    }
C
Cole Robinson 已提交
725
    poolobj->active = 1;
726
    virStoragePoolObjUnlock(poolobj);
C
Cole Robinson 已提交
727

728
    /* Init default node device */
729
    if (!(nodedef = virNodeDeviceDefParseString(defaultNodeXML, 0, NULL)))
730
        goto error;
731
    if (!(nodeobj = virNodeDeviceAssignDef(&privconn->devs,
732 733 734 735 736 737
                                           nodedef))) {
        virNodeDeviceDefFree(nodedef);
        goto error;
    }
    virNodeDeviceObjUnlock(nodeobj);

738 739
    defaultConn = privconn;

740
    virMutexUnlock(&defaultLock);
741

742 743
    return VIR_DRV_OPEN_SUCCESS;

744
 error:
745
    testDriverFree(privconn);
746
    conn->privateData = NULL;
747
    virDomainDefFree(domdef);
748 749
    defaultConnections--;
    virMutexUnlock(&defaultLock);
750
    return VIR_DRV_OPEN_ERROR;
751 752 753 754
}


static char *testBuildFilename(const char *relativeTo,
755 756
                               const char *filename)
{
757 758
    char *offset;
    int baseLen;
759 760
    char *ret;

761
    if (!filename || filename[0] == '\0')
762
        return NULL;
763 764 765 766
    if (filename[0] == '/') {
        ignore_value(VIR_STRDUP(ret, filename));
        return ret;
    }
767

768
    offset = strrchr(relativeTo, '/');
769
    if ((baseLen = (offset-relativeTo+1))) {
770
        char *absFile;
C
Chris Lalancette 已提交
771 772
        int totalLen = baseLen + strlen(filename) + 1;
        if (VIR_ALLOC_N(absFile, totalLen) < 0)
773
            return NULL;
C
Chris Lalancette 已提交
774 775 776 777
        if (virStrncpy(absFile, relativeTo, baseLen, totalLen) == NULL) {
            VIR_FREE(absFile);
            return NULL;
        }
778 779 780
        strcat(absFile, filename);
        return absFile;
    } else {
781 782
        ignore_value(VIR_STRDUP(ret, filename));
        return ret;
783
    }
784 785
}

C
Cole Robinson 已提交
786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816
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;
    }

817
 error:
C
Cole Robinson 已提交
818 819 820 821 822
    xmlFreeDoc(doc);
    VIR_FREE(absFile);
    return ret;
}

823 824 825
static int
testParseNodeInfo(virNodeInfoPtr nodeInfo, xmlXPathContextPtr ctxt)
{
826
    char *str;
827 828
    long l;
    int ret;
829

830
    ret = virXPathLong("string(/node/cpu/nodes[1])", ctxt, &l);
831 832 833
    if (ret == 0) {
        nodeInfo->nodes = l;
    } else if (ret == -2) {
834 835
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu nodes value"));
836
        goto error;
837
    }
838

839
    ret = virXPathLong("string(/node/cpu/sockets[1])", ctxt, &l);
840 841 842
    if (ret == 0) {
        nodeInfo->sockets = l;
    } else if (ret == -2) {
843 844
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu sockets value"));
845
        goto error;
846
    }
847

848
    ret = virXPathLong("string(/node/cpu/cores[1])", ctxt, &l);
849 850 851
    if (ret == 0) {
        nodeInfo->cores = l;
    } else if (ret == -2) {
852 853
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu cores value"));
854
        goto error;
855 856
    }

857
    ret = virXPathLong("string(/node/cpu/threads[1])", ctxt, &l);
858 859 860
    if (ret == 0) {
        nodeInfo->threads = l;
    } else if (ret == -2) {
861 862
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu threads value"));
863
        goto error;
864
    }
865

866 867
    nodeInfo->cpus = (nodeInfo->cores * nodeInfo->threads *
                      nodeInfo->sockets * nodeInfo->nodes);
868
    ret = virXPathLong("string(/node/cpu/active[1])", ctxt, &l);
869
    if (ret == 0) {
870
        if (l < nodeInfo->cpus)
871
            nodeInfo->cpus = l;
872
    } else if (ret == -2) {
873 874
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu active value"));
875
        goto error;
876
    }
877
    ret = virXPathLong("string(/node/cpu/mhz[1])", ctxt, &l);
878 879 880
    if (ret == 0) {
        nodeInfo->mhz = l;
    } else if (ret == -2) {
881 882
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu mhz value"));
883
        goto error;
884 885
    }

886
    str = virXPathString("string(/node/cpu/model[1])", ctxt);
887
    if (str != NULL) {
C
Chris Lalancette 已提交
888
        if (virStrcpyStatic(nodeInfo->model, str) == NULL) {
889 890
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Model %s too big for destination"), str);
C
Chris Lalancette 已提交
891 892 893
            VIR_FREE(str);
            goto error;
        }
894
        VIR_FREE(str);
895 896
    }

897
    ret = virXPathLong("string(/node/memory[1])", ctxt, &l);
898 899 900
    if (ret == 0) {
        nodeInfo->memory = l;
    } else if (ret == -2) {
901 902
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node memory value"));
903
        goto error;
904
    }
905

906
    return 0;
907
 error:
908 909 910
    return -1;
}

911
static int
912
testParseDomainSnapshots(testDriverPtr privconn,
913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962
                         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;
963
 error:
964 965 966
    return ret;
}

967
static int
968
testParseDomains(testDriverPtr privconn,
C
Cole Robinson 已提交
969 970
                 const char *file,
                 xmlXPathContextPtr ctxt)
971 972 973 974 975 976 977
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virDomainObjPtr obj;

    num = virXPathNodeSet("/node/domain", ctxt, &nodes);
978
    if (num < 0)
979 980
        goto error;

981
    for (i = 0; i < num; i++) {
982
        virDomainDefPtr def;
983
        testDomainNamespaceDefPtr nsdata;
C
Cole Robinson 已提交
984 985 986 987 988 989
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file, "domain");
        if (!node)
            goto error;

        def = virDomainDefParseNode(ctxt->doc, node,
                                    privconn->caps, privconn->xmlopt,
990
                                    VIR_DOMAIN_DEF_PARSE_INACTIVE);
C
Cole Robinson 已提交
991 992
        if (!def)
            goto error;
993

994
        if (testDomainGenerateIfnames(def) < 0 ||
995
            !(obj = virDomainObjListAdd(privconn->domains,
996
                                        def,
997
                                        privconn->xmlopt,
998
                                        0, NULL))) {
999
            virDomainDefFree(def);
1000 1001
            goto error;
        }
1002

1003 1004 1005 1006 1007
        if (testParseDomainSnapshots(privconn, obj, file, ctxt) < 0) {
            virObjectUnlock(obj);
            goto error;
        }

1008
        nsdata = def->namespaceData;
1009
        obj->persistent = !nsdata->transient;
C
Cole Robinson 已提交
1010
        obj->hasManagedSave = nsdata->hasManagedSave;
1011 1012 1013 1014 1015 1016 1017 1018 1019

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

1023
        virObjectUnlock(obj);
1024
    }
1025

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

static int
1033
testParseNetworks(testDriverPtr privconn,
C
Cole Robinson 已提交
1034 1035
                  const char *file,
                  xmlXPathContextPtr ctxt)
1036 1037 1038 1039 1040 1041 1042
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virNetworkObjPtr obj;

    num = virXPathNodeSet("/node/network", ctxt, &nodes);
1043
    if (num < 0)
1044
        goto error;
1045 1046

    for (i = 0; i < num; i++) {
1047
        virNetworkDefPtr def;
C
Cole Robinson 已提交
1048 1049 1050
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file, "network");
        if (!node)
            goto error;
1051

C
Cole Robinson 已提交
1052 1053 1054
        def = virNetworkDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
1055

1056
        if (!(obj = virNetworkAssignDef(privconn->networks, def, 0))) {
1057 1058
            virNetworkDefFree(def);
            goto error;
1059
        }
1060 1061

        obj->active = 1;
1062
        virNetworkObjEndAPI(&obj);
1063
    }
1064

1065
    ret = 0;
1066
 error:
1067 1068 1069 1070 1071
    VIR_FREE(nodes);
    return ret;
}

static int
1072
testParseInterfaces(testDriverPtr privconn,
C
Cole Robinson 已提交
1073 1074
                    const char *file,
                    xmlXPathContextPtr ctxt)
1075 1076 1077 1078 1079 1080 1081
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virInterfaceObjPtr obj;

    num = virXPathNodeSet("/node/interface", ctxt, &nodes);
1082
    if (num < 0)
L
Laine Stump 已提交
1083
        goto error;
1084 1085

    for (i = 0; i < num; i++) {
L
Laine Stump 已提交
1086
        virInterfaceDefPtr def;
C
Cole Robinson 已提交
1087 1088 1089 1090
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "interface");
        if (!node)
            goto error;
L
Laine Stump 已提交
1091

C
Cole Robinson 已提交
1092 1093 1094
        def = virInterfaceDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
1095

1096
        if (!(obj = virInterfaceAssignDef(&privconn->ifaces, def))) {
L
Laine Stump 已提交
1097 1098 1099
            virInterfaceDefFree(def);
            goto error;
        }
1100

1101 1102 1103 1104 1105
        obj->active = 1;
        virInterfaceObjUnlock(obj);
    }

    ret = 0;
1106
 error:
1107 1108 1109 1110 1111
    VIR_FREE(nodes);
    return ret;
}

static int
C
Cole Robinson 已提交
1112
testOpenVolumesForPool(const char *file,
1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128
                       xmlXPathContextPtr ctxt,
                       virStoragePoolObjPtr pool,
                       int poolidx)
{
    char *vol_xpath;
    size_t i;
    int num, ret = -1;
    xmlNodePtr *nodes = NULL;
    virStorageVolDefPtr def = NULL;

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

    num = virXPathNodeSet(vol_xpath, ctxt, &nodes);
    VIR_FREE(vol_xpath);
1129
    if (num < 0)
1130 1131 1132
        goto error;

    for (i = 0; i < num; i++) {
C
Cole Robinson 已提交
1133 1134 1135 1136
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "volume");
        if (!node)
            goto error;
1137

1138
        def = virStorageVolDefParseNode(pool->def, ctxt->doc, node, 0);
C
Cole Robinson 已提交
1139 1140
        if (!def)
            goto error;
1141 1142 1143 1144 1145 1146 1147 1148 1149 1150

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

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

1154
        pool->def->allocation += def->target.allocation;
1155 1156 1157
        pool->def->available = (pool->def->capacity -
                                pool->def->allocation);
        def = NULL;
L
Laine Stump 已提交
1158 1159
    }

1160
    ret = 0;
1161
 error:
1162 1163 1164 1165 1166 1167
    virStorageVolDefFree(def);
    VIR_FREE(nodes);
    return ret;
}

static int
1168
testParseStorage(testDriverPtr privconn,
C
Cole Robinson 已提交
1169 1170
                 const char *file,
                 xmlXPathContextPtr ctxt)
1171 1172 1173 1174 1175 1176 1177
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virStoragePoolObjPtr obj;

    num = virXPathNodeSet("/node/pool", ctxt, &nodes);
1178
    if (num < 0)
C
Cole Robinson 已提交
1179
        goto error;
1180 1181

    for (i = 0; i < num; i++) {
C
Cole Robinson 已提交
1182
        virStoragePoolDefPtr def;
C
Cole Robinson 已提交
1183 1184 1185 1186
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "pool");
        if (!node)
            goto error;
C
Cole Robinson 已提交
1187

C
Cole Robinson 已提交
1188 1189 1190
        def = virStoragePoolDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
C
Cole Robinson 已提交
1191

1192
        if (!(obj = virStoragePoolObjAssignDef(&privconn->pools,
C
Cole Robinson 已提交
1193 1194 1195 1196 1197
                                                def))) {
            virStoragePoolDefFree(def);
            goto error;
        }

1198 1199
        if (testStoragePoolObjSetDefaults(obj) == -1) {
            virStoragePoolObjUnlock(obj);
C
Cole Robinson 已提交
1200
            goto error;
1201
        }
1202
        obj->active = 1;
1203 1204

        /* Find storage volumes */
C
Cole Robinson 已提交
1205
        if (testOpenVolumesForPool(file, ctxt, obj, i+1) < 0) {
1206
            virStoragePoolObjUnlock(obj);
1207 1208 1209
            goto error;
        }

1210
        virStoragePoolObjUnlock(obj);
C
Cole Robinson 已提交
1211 1212
    }

1213
    ret = 0;
1214
 error:
1215 1216 1217 1218 1219
    VIR_FREE(nodes);
    return ret;
}

static int
1220
testParseNodedevs(testDriverPtr privconn,
C
Cole Robinson 已提交
1221 1222
                  const char *file,
                  xmlXPathContextPtr ctxt)
1223 1224 1225 1226 1227 1228 1229
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virNodeDeviceObjPtr obj;

    num = virXPathNodeSet("/node/device", ctxt, &nodes);
1230
    if (num < 0)
1231
        goto error;
1232 1233

    for (i = 0; i < num; i++) {
1234
        virNodeDeviceDefPtr def;
C
Cole Robinson 已提交
1235 1236 1237 1238
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                  "nodedev");
        if (!node)
            goto error;
1239

C
Cole Robinson 已提交
1240 1241 1242
        def = virNodeDeviceDefParseNode(ctxt->doc, node, 0, NULL);
        if (!def)
            goto error;
1243 1244

        if (!(obj = virNodeDeviceAssignDef(&privconn->devs, def))) {
1245 1246 1247
            virNodeDeviceDefFree(def);
            goto error;
        }
1248 1249 1250 1251 1252

        virNodeDeviceObjUnlock(obj);
    }

    ret = 0;
1253
 error:
1254 1255 1256 1257
    VIR_FREE(nodes);
    return ret;
}

1258
static int
1259
testParseAuthUsers(testDriverPtr privconn,
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292
                   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;
1293
 error:
1294 1295 1296
    VIR_FREE(nodes);
    return ret;
}
1297 1298 1299

/* No shared state between simultaneous test connections initialized
 * from a file.  */
1300 1301 1302 1303 1304
static int
testOpenFromFile(virConnectPtr conn, const char *file)
{
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
1305
    testDriverPtr privconn;
1306

1307
    if (!(privconn = testDriverNew()))
1308
        return VIR_DRV_OPEN_ERROR;
1309

1310 1311 1312 1313 1314 1315
    testDriverLock(privconn);
    conn->privateData = privconn;

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

1316
    if (!(doc = virXMLParseFileCtxt(file, &ctxt)))
1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329
        goto error;

    if (!xmlStrEqual(ctxt->node->name, BAD_CAST "node")) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("Root element is not 'node'"));
        goto error;
    }

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

    if (testParseNodeInfo(&privconn->nodeInfo, ctxt) < 0)
        goto error;
C
Cole Robinson 已提交
1330
    if (testParseDomains(privconn, file, ctxt) < 0)
1331
        goto error;
C
Cole Robinson 已提交
1332
    if (testParseNetworks(privconn, file, ctxt) < 0)
1333
        goto error;
C
Cole Robinson 已提交
1334
    if (testParseInterfaces(privconn, file, ctxt) < 0)
1335
        goto error;
C
Cole Robinson 已提交
1336
    if (testParseStorage(privconn, file, ctxt) < 0)
1337
        goto error;
C
Cole Robinson 已提交
1338
    if (testParseNodedevs(privconn, file, ctxt) < 0)
1339
        goto error;
1340 1341
    if (testParseAuthUsers(privconn, ctxt) < 0)
        goto error;
1342

J
Jim Meyering 已提交
1343
    xmlXPathFreeContext(ctxt);
1344
    xmlFreeDoc(doc);
1345
    testDriverUnlock(privconn);
1346

1347
    return 0;
1348 1349

 error:
J
Jim Meyering 已提交
1350
    xmlXPathFreeContext(ctxt);
1351
    xmlFreeDoc(doc);
1352
    testDriverFree(privconn);
1353
    conn->privateData = NULL;
1354
    return VIR_DRV_OPEN_ERROR;
1355 1356
}

1357 1358 1359 1360
static int
testConnectAuthenticate(virConnectPtr conn,
                        virConnectAuthPtr auth)
{
1361
    testDriverPtr privconn = conn->privateData;
1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385
    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;

1386
 found_user:
1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405
    /* 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;
1406
 cleanup:
1407 1408 1409 1410
    VIR_FREE(username);
    VIR_FREE(password);
    return ret;
}
1411

1412
static virDrvOpenStatus testConnectOpen(virConnectPtr conn,
1413
                                        virConnectAuthPtr auth,
1414
                                        unsigned int flags)
1415
{
1416
    int ret;
1417

E
Eric Blake 已提交
1418 1419
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

1420
    if (!conn->uri)
1421
        return VIR_DRV_OPEN_DECLINED;
1422

1423
    if (!conn->uri->scheme || STRNEQ(conn->uri->scheme, "test"))
1424
        return VIR_DRV_OPEN_DECLINED;
1425

1426
    /* Remote driver should handle these. */
1427
    if (conn->uri->server)
1428 1429
        return VIR_DRV_OPEN_DECLINED;

1430
    /* From this point on, the connection is for us. */
1431 1432 1433
    if (!conn->uri->path
        || conn->uri->path[0] == '\0'
        || (conn->uri->path[0] == '/' && conn->uri->path[1] == '\0')) {
1434 1435
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("testOpen: supply a path or use test:///default"));
1436 1437
        return VIR_DRV_OPEN_ERROR;
    }
1438

1439
    if (STREQ(conn->uri->path, "/default"))
1440 1441
        ret = testOpenDefault(conn);
    else
1442
        ret = testOpenFromFile(conn,
1443
                               conn->uri->path);
1444

1445 1446 1447
    if (ret != VIR_DRV_OPEN_SUCCESS)
        return ret;

1448 1449 1450 1451
    /* Fake authentication. */
    if (testConnectAuthenticate(conn, auth) < 0)
        return VIR_DRV_OPEN_ERROR;

1452
    return VIR_DRV_OPEN_SUCCESS;
1453 1454
}

1455
static int testConnectClose(virConnectPtr conn)
1456
{
1457
    testDriverPtr privconn = conn->privateData;
1458
    bool dflt = false;
1459

1460 1461
    if (privconn == defaultConn) {
        dflt = true;
1462 1463 1464 1465 1466 1467 1468
        virMutexLock(&defaultLock);
        if (--defaultConnections) {
            virMutexUnlock(&defaultLock);
            return 0;
        }
    }

1469
    testDriverLock(privconn);
1470
    testDriverFree(privconn);
1471 1472 1473

    if (dflt) {
        defaultConn = NULL;
1474
        virMutexUnlock(&defaultLock);
1475 1476
    }

1477
    conn->privateData = NULL;
1478
    return 0;
1479 1480
}

1481 1482
static int testConnectGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
                                 unsigned long *hvVer)
1483
{
1484
    *hvVer = 2;
1485
    return 0;
1486 1487
}

1488 1489 1490 1491 1492 1493
static char *testConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return virGetHostname();
}


1494
static int testConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
1495 1496 1497 1498
{
    return 1;
}

1499
static int testConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
1500 1501 1502 1503
{
    return 0;
}

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

1509 1510
static int testConnectGetMaxVcpus(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type ATTRIBUTE_UNUSED)
1511 1512 1513 1514
{
    return 32;
}

1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529
static char *
testConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED,
                       const char **xmlCPUs,
                       unsigned int ncpus,
                       unsigned int flags)
{
    char *cpu;

    virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, NULL);

    cpu = cpuBaselineXML(xmlCPUs, ncpus, NULL, 0, flags);

    return cpu;
}

1530 1531
static int testNodeGetInfo(virConnectPtr conn,
                           virNodeInfoPtr info)
1532
{
1533
    testDriverPtr privconn = conn->privateData;
1534
    testDriverLock(privconn);
1535
    memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo));
1536
    testDriverUnlock(privconn);
1537
    return 0;
1538 1539
}

1540
static char *testConnectGetCapabilities(virConnectPtr conn)
1541
{
1542
    testDriverPtr privconn = conn->privateData;
1543
    char *xml;
1544
    testDriverLock(privconn);
1545
    xml = virCapabilitiesFormatXML(privconn->caps);
1546
    testDriverUnlock(privconn);
1547
    return xml;
1548 1549
}

1550
static int testConnectNumOfDomains(virConnectPtr conn)
1551
{
1552
    testDriverPtr privconn = conn->privateData;
1553
    int count;
1554

1555
    testDriverLock(privconn);
1556
    count = virDomainObjListNumOfDomains(privconn->domains, true, NULL, NULL);
1557
    testDriverUnlock(privconn);
1558

1559
    return count;
1560 1561
}

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

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

1570 1571
    ret = virDomainObjIsActive(obj);
    virDomainObjEndAPI(&obj);
1572 1573 1574 1575 1576 1577
    return ret;
}

static int testDomainIsPersistent(virDomainPtr dom)
{
    virDomainObjPtr obj;
1578 1579 1580 1581
    int ret;

    if (!(obj = testDomObjFromDomain(dom)))
        return -1;
1582 1583 1584

    ret = obj->persistent;

1585
    virDomainObjEndAPI(&obj);
1586 1587 1588
    return ret;
}

1589 1590 1591 1592 1593
static int testDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
{
    return 0;
}

1594
static virDomainPtr
1595
testDomainCreateXML(virConnectPtr conn, const char *xml,
1596
                      unsigned int flags)
1597
{
1598
    testDriverPtr privconn = conn->privateData;
1599
    virDomainPtr ret = NULL;
1600
    virDomainDefPtr def;
1601
    virDomainObjPtr dom = NULL;
1602
    virObjectEventPtr event = NULL;
1603
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
1604

1605 1606 1607
    virCheckFlags(VIR_DOMAIN_START_VALIDATE, NULL);

    if (flags & VIR_DOMAIN_START_VALIDATE)
1608
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
1609

1610
    testDriverLock(privconn);
1611
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
1612
                                       parse_flags)) == NULL)
1613
        goto cleanup;
1614

1615
    if (testDomainGenerateIfnames(def) < 0)
1616
        goto cleanup;
1617
    if (!(dom = virDomainObjListAdd(privconn->domains,
1618
                                    def,
1619
                                    privconn->xmlopt,
1620
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
1621 1622
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
1623 1624
        goto cleanup;
    def = NULL;
1625

1626 1627 1628 1629 1630
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_BOOTED) < 0) {
        if (!dom->persistent) {
            virDomainObjListRemove(privconn->domains, dom);
            dom = NULL;
        }
1631
        goto cleanup;
1632
    }
1633

1634
    event = virDomainEventLifecycleNewFromObj(dom,
1635 1636 1637
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);

1638
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1639
    if (ret)
1640
        ret->id = dom->def->id;
1641

1642
 cleanup:
1643
    if (dom)
1644
        virObjectUnlock(dom);
1645
    testObjectEventQueue(privconn, event);
1646
    virDomainDefFree(def);
1647
    testDriverUnlock(privconn);
1648
    return ret;
1649 1650 1651
}


1652
static virDomainPtr testDomainLookupByID(virConnectPtr conn,
1653
                                         int id)
1654
{
1655
    testDriverPtr privconn = conn->privateData;
1656 1657
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1658

1659
    if (!(dom = virDomainObjListFindByID(privconn->domains, id))) {
1660
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1661
        goto cleanup;
1662 1663
    }

1664
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1665 1666 1667
    if (ret)
        ret->id = dom->def->id;

1668
 cleanup:
1669
    if (dom)
1670
        virObjectUnlock(dom);
1671
    return ret;
1672 1673
}

1674
static virDomainPtr testDomainLookupByUUID(virConnectPtr conn,
1675
                                           const unsigned char *uuid)
1676
{
1677
    testDriverPtr privconn = conn->privateData;
1678
    virDomainPtr ret = NULL;
1679
    virDomainObjPtr dom;
1680

1681
    if (!(dom = virDomainObjListFindByUUID(privconn->domains, uuid))) {
1682
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1683
        goto cleanup;
1684
    }
1685

1686
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1687 1688 1689
    if (ret)
        ret->id = dom->def->id;

1690
 cleanup:
1691
    if (dom)
1692
        virObjectUnlock(dom);
1693
    return ret;
1694 1695
}

1696
static virDomainPtr testDomainLookupByName(virConnectPtr conn,
1697
                                           const char *name)
1698
{
1699
    testDriverPtr privconn = conn->privateData;
1700 1701
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1702

1703
    if (!(dom = virDomainObjListFindByName(privconn->domains, name))) {
1704
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1705
        goto cleanup;
1706
    }
1707

1708
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1709 1710 1711
    if (ret)
        ret->id = dom->def->id;

1712
 cleanup:
1713
    virDomainObjEndAPI(&dom);
1714
    return ret;
1715 1716
}

1717 1718 1719
static int testConnectListDomains(virConnectPtr conn,
                                  int *ids,
                                  int maxids)
1720
{
1721
    testDriverPtr privconn = conn->privateData;
1722

1723 1724
    return virDomainObjListGetActiveIDs(privconn->domains, ids, maxids,
                                        NULL, NULL);
1725 1726
}

1727
static int testDomainDestroy(virDomainPtr domain)
1728
{
1729
    testDriverPtr privconn = domain->conn->privateData;
1730
    virDomainObjPtr privdom;
1731
    virObjectEventPtr event = NULL;
1732
    int ret = -1;
1733 1734


1735
    if (!(privdom = testDomObjFromDomain(domain)))
1736
        goto cleanup;
1737

J
Jiri Denemark 已提交
1738
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_DESTROYED);
1739
    event = virDomainEventLifecycleNewFromObj(privdom,
1740 1741
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
1742

1743 1744
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
1745 1746

    ret = 0;
1747
 cleanup:
1748
    virDomainObjEndAPI(&privdom);
1749
    testObjectEventQueue(privconn, event);
1750
    return ret;
1751 1752
}

1753
static int testDomainResume(virDomainPtr domain)
1754
{
1755
    testDriverPtr privconn = domain->conn->privateData;
1756
    virDomainObjPtr privdom;
1757
    virObjectEventPtr event = NULL;
1758
    int ret = -1;
1759

1760 1761
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1762

J
Jiri Denemark 已提交
1763
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_PAUSED) {
1764 1765
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"),
                       domain->name);
1766
        goto cleanup;
1767
    }
1768

J
Jiri Denemark 已提交
1769 1770
    virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                         VIR_DOMAIN_RUNNING_UNPAUSED);
1771
    event = virDomainEventLifecycleNewFromObj(privdom,
1772 1773
                                     VIR_DOMAIN_EVENT_RESUMED,
                                     VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
1774 1775
    ret = 0;

1776
 cleanup:
1777
    virDomainObjEndAPI(&privdom);
1778
    testObjectEventQueue(privconn, event);
1779
    return ret;
1780 1781
}

1782
static int testDomainSuspend(virDomainPtr domain)
1783
{
1784
    testDriverPtr privconn = domain->conn->privateData;
1785
    virDomainObjPtr privdom;
1786
    virObjectEventPtr event = NULL;
1787
    int ret = -1;
J
Jiri Denemark 已提交
1788
    int state;
1789

1790 1791
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1792

J
Jiri Denemark 已提交
1793 1794
    state = virDomainObjGetState(privdom, NULL);
    if (state == VIR_DOMAIN_SHUTOFF || state == VIR_DOMAIN_PAUSED) {
1795 1796
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"),
                       domain->name);
1797
        goto cleanup;
1798
    }
1799

J
Jiri Denemark 已提交
1800
    virDomainObjSetState(privdom, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
1801
    event = virDomainEventLifecycleNewFromObj(privdom,
1802 1803
                                     VIR_DOMAIN_EVENT_SUSPENDED,
                                     VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
1804 1805
    ret = 0;

1806
 cleanup:
1807
    virDomainObjEndAPI(&privdom);
1808
    testObjectEventQueue(privconn, event);
1809
    return ret;
1810 1811
}

1812
static int testDomainShutdownFlags(virDomainPtr domain,
1813
                                   unsigned int flags)
1814
{
1815
    testDriverPtr privconn = domain->conn->privateData;
1816
    virDomainObjPtr privdom;
1817
    virObjectEventPtr event = NULL;
1818
    int ret = -1;
1819

1820 1821
    virCheckFlags(0, -1);

1822

1823
    if (!(privdom = testDomObjFromDomain(domain)))
1824
        goto cleanup;
1825

J
Jiri Denemark 已提交
1826
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
1827 1828
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("domain '%s' not running"), domain->name);
1829
        goto cleanup;
1830
    }
1831

J
Jiri Denemark 已提交
1832
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1833
    event = virDomainEventLifecycleNewFromObj(privdom,
1834 1835
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1836

1837 1838
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
1839

1840
    ret = 0;
1841
 cleanup:
1842
    virDomainObjEndAPI(&privdom);
1843
    testObjectEventQueue(privconn, event);
1844
    return ret;
1845 1846
}

1847
static int testDomainShutdown(virDomainPtr domain)
1848
{
1849
    return testDomainShutdownFlags(domain, 0);
1850 1851
}

1852
/* Similar behaviour as shutdown */
1853
static int testDomainReboot(virDomainPtr domain,
1854
                            unsigned int action ATTRIBUTE_UNUSED)
1855
{
1856
    testDriverPtr privconn = domain->conn->privateData;
1857
    virDomainObjPtr privdom;
1858
    virObjectEventPtr event = NULL;
1859
    int ret = -1;
1860 1861


1862
    if (!(privdom = testDomObjFromDomain(domain)))
1863
        goto cleanup;
1864

J
Jiri Denemark 已提交
1865 1866 1867
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTDOWN,
                         VIR_DOMAIN_SHUTDOWN_USER);

1868 1869
    switch (privdom->def->onReboot) {
    case VIR_DOMAIN_LIFECYCLE_DESTROY:
J
Jiri Denemark 已提交
1870 1871
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1872 1873
        break;

1874
    case VIR_DOMAIN_LIFECYCLE_RESTART:
J
Jiri Denemark 已提交
1875 1876
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
1877 1878
        break;

1879
    case VIR_DOMAIN_LIFECYCLE_PRESERVE:
J
Jiri Denemark 已提交
1880 1881
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1882 1883
        break;

1884
    case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME:
J
Jiri Denemark 已提交
1885 1886
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
1887
        break;
1888

1889
    default:
J
Jiri Denemark 已提交
1890 1891
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1892 1893
        break;
    }
1894

J
Jiri Denemark 已提交
1895 1896
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1897
        event = virDomainEventLifecycleNewFromObj(privdom,
1898 1899
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1900

1901 1902
        if (!privdom->persistent)
            virDomainObjListRemove(privconn->domains, privdom);
1903 1904
    }

1905
    ret = 0;
1906
 cleanup:
1907
    virDomainObjEndAPI(&privdom);
1908
    testObjectEventQueue(privconn, event);
1909
    return ret;
1910 1911
}

1912
static int testDomainGetInfo(virDomainPtr domain,
1913
                             virDomainInfoPtr info)
1914
{
1915
    struct timeval tv;
1916
    virDomainObjPtr privdom;
1917
    int ret = -1;
1918

1919 1920
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1921 1922

    if (gettimeofday(&tv, NULL) < 0) {
1923 1924
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("getting time of day"));
1925
        goto cleanup;
1926 1927
    }

J
Jiri Denemark 已提交
1928
    info->state = virDomainObjGetState(privdom, NULL);
1929
    info->memory = privdom->def->mem.cur_balloon;
1930
    info->maxMem = virDomainDefGetMemoryActual(privdom->def);
1931
    info->nrVirtCpu = virDomainDefGetVcpus(privdom->def);
1932
    info->cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
1933 1934
    ret = 0;

1935
 cleanup:
1936
    virDomainObjEndAPI(&privdom);
1937
    return ret;
1938 1939
}

1940 1941 1942 1943 1944 1945 1946 1947 1948 1949
static int
testDomainGetState(virDomainPtr domain,
                   int *state,
                   int *reason,
                   unsigned int flags)
{
    virDomainObjPtr privdom;

    virCheckFlags(0, -1);

1950 1951
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1952

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

1955
    virDomainObjEndAPI(&privdom);
1956 1957

    return 0;
1958 1959
}

1960 1961
#define TEST_SAVE_MAGIC "TestGuestMagic"

1962 1963 1964
static int
testDomainSaveFlags(virDomainPtr domain, const char *path,
                    const char *dxml, unsigned int flags)
1965
{
1966
    testDriverPtr privconn = domain->conn->privateData;
1967 1968 1969
    char *xml = NULL;
    int fd = -1;
    int len;
1970
    virDomainObjPtr privdom;
1971
    virObjectEventPtr event = NULL;
1972
    int ret = -1;
1973

1974 1975
    virCheckFlags(0, -1);
    if (dxml) {
1976 1977
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1978 1979 1980
        return -1;
    }

1981

1982
    if (!(privdom = testDomObjFromDomain(domain)))
1983
        goto cleanup;
1984

1985
    xml = virDomainDefFormat(privdom->def, privconn->caps,
1986
                             VIR_DOMAIN_DEF_FORMAT_SECURE);
C
Cole Robinson 已提交
1987

1988
    if (xml == NULL) {
1989
        virReportSystemError(errno,
1990 1991
                             _("saving domain '%s' failed to allocate space for metadata"),
                             domain->name);
1992
        goto cleanup;
1993
    }
1994 1995

    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
1996
        virReportSystemError(errno,
1997 1998
                             _("saving domain '%s' to '%s': open failed"),
                             domain->name, path);
1999
        goto cleanup;
2000
    }
2001
    len = strlen(xml);
2002
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
2003
        virReportSystemError(errno,
2004 2005
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
2006
        goto cleanup;
2007
    }
2008
    if (safewrite(fd, (char*)&len, sizeof(len)) < 0) {
2009
        virReportSystemError(errno,
2010 2011
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
2012
        goto cleanup;
2013
    }
2014
    if (safewrite(fd, xml, len) < 0) {
2015
        virReportSystemError(errno,
2016 2017
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
2018
        goto cleanup;
2019
    }
2020

2021
    if (VIR_CLOSE(fd) < 0) {
2022
        virReportSystemError(errno,
2023 2024
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
2025
        goto cleanup;
2026
    }
2027 2028
    fd = -1;

J
Jiri Denemark 已提交
2029
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SAVED);
2030
    event = virDomainEventLifecycleNewFromObj(privdom,
2031 2032
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
2033

2034 2035
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
2036

2037
    ret = 0;
2038
 cleanup:
2039 2040 2041 2042 2043 2044
    VIR_FREE(xml);

    /* Don't report failure in close or unlink, because
     * in either case we're already in a failure scenario
     * and have reported a earlier error */
    if (ret != 0) {
2045
        VIR_FORCE_CLOSE(fd);
2046 2047
        unlink(path);
    }
2048
    virDomainObjEndAPI(&privdom);
2049
    testObjectEventQueue(privconn, event);
2050
    return ret;
2051 2052
}

2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064
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)
2065
{
2066
    testDriverPtr privconn = conn->privateData;
2067
    char *xml = NULL;
2068
    char magic[15];
2069 2070 2071
    int fd = -1;
    int len;
    virDomainDefPtr def = NULL;
2072
    virDomainObjPtr dom = NULL;
2073
    virObjectEventPtr event = NULL;
2074
    int ret = -1;
2075

2076 2077
    virCheckFlags(0, -1);
    if (dxml) {
2078 2079
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
2080 2081 2082
        return -1;
    }

2083
    if ((fd = open(path, O_RDONLY)) < 0) {
2084
        virReportSystemError(errno,
2085 2086
                             _("cannot read domain image '%s'"),
                             path);
2087
        goto cleanup;
2088
    }
2089
    if (saferead(fd, magic, sizeof(magic)) != sizeof(magic)) {
2090
        virReportSystemError(errno,
2091 2092
                             _("incomplete save header in '%s'"),
                             path);
2093
        goto cleanup;
2094
    }
2095
    if (memcmp(magic, TEST_SAVE_MAGIC, sizeof(magic))) {
2096 2097
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("mismatched header magic"));
2098
        goto cleanup;
2099
    }
2100
    if (saferead(fd, (char*)&len, sizeof(len)) != sizeof(len)) {
2101
        virReportSystemError(errno,
2102 2103
                             _("failed to read metadata length in '%s'"),
                             path);
2104
        goto cleanup;
2105 2106
    }
    if (len < 1 || len > 8192) {
2107 2108
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("length of metadata out of range"));
2109
        goto cleanup;
2110
    }
2111
    if (VIR_ALLOC_N(xml, len+1) < 0)
2112
        goto cleanup;
2113
    if (saferead(fd, xml, len) != len) {
2114
        virReportSystemError(errno,
2115
                             _("incomplete metadata in '%s'"), path);
2116
        goto cleanup;
2117 2118
    }
    xml[len] = '\0';
2119

2120
    def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
2121
                                  VIR_DOMAIN_DEF_PARSE_INACTIVE);
2122
    if (!def)
2123
        goto cleanup;
2124

2125
    if (testDomainGenerateIfnames(def) < 0)
2126
        goto cleanup;
2127
    if (!(dom = virDomainObjListAdd(privconn->domains,
2128
                                    def,
2129
                                    privconn->xmlopt,
2130 2131 2132
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
2133 2134
        goto cleanup;
    def = NULL;
2135

2136 2137 2138 2139 2140
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_RESTORED) < 0) {
        if (!dom->persistent) {
            virDomainObjListRemove(privconn->domains, dom);
            dom = NULL;
        }
2141
        goto cleanup;
2142
    }
2143

2144
    event = virDomainEventLifecycleNewFromObj(dom,
2145 2146
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
2147
    ret = 0;
2148

2149
 cleanup:
2150 2151
    virDomainDefFree(def);
    VIR_FREE(xml);
2152
    VIR_FORCE_CLOSE(fd);
2153
    if (dom)
2154
        virObjectUnlock(dom);
2155
    testObjectEventQueue(privconn, event);
2156
    return ret;
2157 2158
}

2159 2160 2161 2162 2163 2164 2165
static int
testDomainRestore(virConnectPtr conn,
                  const char *path)
{
    return testDomainRestoreFlags(conn, path, NULL, 0);
}

2166 2167 2168 2169
static int testDomainCoreDumpWithFormat(virDomainPtr domain,
                                        const char *to,
                                        unsigned int dumpformat,
                                        unsigned int flags)
2170
{
2171
    testDriverPtr privconn = domain->conn->privateData;
2172
    int fd = -1;
2173
    virDomainObjPtr privdom;
2174
    virObjectEventPtr event = NULL;
2175
    int ret = -1;
2176

E
Eric Blake 已提交
2177 2178
    virCheckFlags(VIR_DUMP_CRASH, -1);

2179

2180
    if (!(privdom = testDomObjFromDomain(domain)))
2181
        goto cleanup;
2182 2183

    if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
2184
        virReportSystemError(errno,
2185 2186
                             _("domain '%s' coredump: failed to open %s"),
                             domain->name, to);
2187
        goto cleanup;
2188
    }
2189
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
2190
        virReportSystemError(errno,
2191 2192
                             _("domain '%s' coredump: failed to write header to %s"),
                             domain->name, to);
2193
        goto cleanup;
2194
    }
2195
    if (VIR_CLOSE(fd) < 0) {
2196
        virReportSystemError(errno,
2197 2198
                             _("domain '%s' coredump: write failed: %s"),
                             domain->name, to);
2199
        goto cleanup;
2200
    }
2201

2202 2203 2204 2205 2206 2207 2208
    /* 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;
    }

2209
    if (flags & VIR_DUMP_CRASH) {
J
Jiri Denemark 已提交
2210
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_CRASHED);
2211
        event = virDomainEventLifecycleNewFromObj(privdom,
2212 2213
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
2214 2215
        if (!privdom->persistent)
            virDomainObjListRemove(privconn->domains, privdom);
2216
    }
2217

2218
    ret = 0;
2219
 cleanup:
2220
    VIR_FORCE_CLOSE(fd);
2221
    virDomainObjEndAPI(&privdom);
2222
    testObjectEventQueue(privconn, event);
2223
    return ret;
2224 2225
}

2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239

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)
{
2240 2241 2242
    char *ret;

    ignore_value(VIR_STRDUP(ret, "linux"));
2243
    return ret;
2244 2245
}

2246 2247 2248

static unsigned long long
testDomainGetMaxMemory(virDomainPtr domain)
2249
{
2250
    virDomainObjPtr privdom;
2251
    unsigned long long ret = 0;
2252

2253 2254
    if (!(privdom = testDomObjFromDomain(domain)))
        return 0;
2255

2256
    ret = virDomainDefGetMemoryActual(privdom->def);
2257

2258
    virDomainObjEndAPI(&privdom);
2259
    return ret;
2260 2261
}

2262 2263
static int testDomainSetMaxMemory(virDomainPtr domain,
                                  unsigned long memory)
2264
{
2265 2266
    virDomainObjPtr privdom;

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

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

2273
    virDomainObjEndAPI(&privdom);
2274
    return 0;
2275 2276
}

2277 2278
static int testDomainSetMemory(virDomainPtr domain,
                               unsigned long memory)
2279
{
2280
    virDomainObjPtr privdom;
2281
    int ret = -1;
2282

2283 2284
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2285

2286
    if (memory > virDomainDefGetMemoryActual(privdom->def)) {
2287
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2288
        goto cleanup;
2289
    }
2290

2291
    privdom->def->mem.cur_balloon = memory;
2292 2293
    ret = 0;

2294
 cleanup:
2295
    virDomainObjEndAPI(&privdom);
2296
    return ret;
2297 2298
}

2299 2300
static int
testDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
C
Cole Robinson 已提交
2301
{
2302 2303 2304 2305
    virDomainObjPtr vm;
    virDomainDefPtr def;
    int ret = -1;

2306 2307
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2308 2309
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

2310 2311
    if (!(vm = testDomObjFromDomain(domain)))
        return -1;
2312

2313
    if (!(def = virDomainObjGetOneDef(vm, flags)))
2314
        goto cleanup;
2315

2316 2317 2318
    if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
        ret = virDomainDefGetVcpusMax(def);
    else
2319
        ret = virDomainDefGetVcpus(def);
2320

2321
 cleanup:
2322
    virDomainObjEndAPI(&vm);
2323
    return ret;
C
Cole Robinson 已提交
2324 2325
}

2326 2327 2328
static int
testDomainGetMaxVcpus(virDomainPtr domain)
{
2329
    return testDomainGetVcpusFlags(domain, (VIR_DOMAIN_AFFECT_LIVE |
2330 2331 2332 2333 2334 2335 2336
                                            VIR_DOMAIN_VCPU_MAXIMUM));
}

static int
testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
                        unsigned int flags)
{
2337
    virDomainObjPtr privdom = NULL;
2338
    virDomainDefPtr def;
2339
    virDomainDefPtr persistentDef;
C
Cole Robinson 已提交
2340 2341
    int ret = -1, maxvcpus;

2342 2343
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2344 2345
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

2346
    if ((maxvcpus = testConnectGetMaxVcpus(domain->conn, NULL)) < 0)
2347
        return -1;
2348 2349

    if (nrCpus > maxvcpus) {
2350
        virReportError(VIR_ERR_INVALID_ARG,
2351 2352
                       _("requested cpu amount exceeds maximum supported amount "
                         "(%d > %d)"), nrCpus, maxvcpus);
2353 2354
        return -1;
    }
2355

2356 2357
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2358

2359
    if (virDomainObjGetDefs(privdom, flags, &def, &persistentDef) < 0)
C
Cole Robinson 已提交
2360 2361
        goto cleanup;

2362
    if (def && virDomainDefGetVcpusMax(def) < nrCpus) {
2363 2364
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested cpu amount exceeds maximum (%d > %d)"),
2365
                       nrCpus, virDomainDefGetVcpusMax(def));
2366
        goto cleanup;
2367
    }
2368

2369 2370
    if (persistentDef &&
        !(flags & VIR_DOMAIN_VCPU_MAXIMUM) &&
2371
        virDomainDefGetVcpusMax(persistentDef) < nrCpus) {
2372 2373
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested cpu amount exceeds maximum (%d > %d)"),
2374
                       nrCpus, virDomainDefGetVcpusMax(persistentDef));
2375
        goto cleanup;
2376
    }
2377

2378 2379 2380
    if (def &&
        virDomainDefSetVcpus(def, nrCpus) < 0)
        goto cleanup;
2381

2382 2383
    if (persistentDef) {
        if (flags & VIR_DOMAIN_VCPU_MAXIMUM) {
2384 2385
            if (virDomainDefSetVcpusMax(persistentDef, nrCpus) < 0)
                goto cleanup;
2386
        } else {
2387 2388
            if (virDomainDefSetVcpus(persistentDef, nrCpus) < 0)
                goto cleanup;
2389
        }
2390
    }
2391

2392 2393
    ret = 0;

2394
 cleanup:
2395
    virDomainObjEndAPI(&privdom);
2396
    return ret;
2397 2398
}

2399
static int
2400
testDomainSetVcpus(virDomainPtr domain, unsigned int nrCpus)
2401
{
2402
    return testDomainSetVcpusFlags(domain, nrCpus, VIR_DOMAIN_AFFECT_LIVE);
2403 2404
}

C
Cole Robinson 已提交
2405 2406 2407 2408 2409 2410
static int testDomainGetVcpus(virDomainPtr domain,
                              virVcpuInfoPtr info,
                              int maxinfo,
                              unsigned char *cpumaps,
                              int maplen)
{
2411
    testDriverPtr privconn = domain->conn->privateData;
C
Cole Robinson 已提交
2412
    virDomainObjPtr privdom;
2413
    virDomainDefPtr def;
2414
    size_t i;
2415
    int maxcpu, hostcpus;
C
Cole Robinson 已提交
2416 2417 2418
    int ret = -1;
    struct timeval tv;
    unsigned long long statbase;
2419
    virBitmapPtr allcpumap = NULL;
C
Cole Robinson 已提交
2420

2421 2422
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
C
Cole Robinson 已提交
2423 2424

    if (!virDomainObjIsActive(privdom)) {
2425
        virReportError(VIR_ERR_OPERATION_INVALID,
2426
                       "%s", _("cannot list vcpus for an inactive domain"));
C
Cole Robinson 已提交
2427 2428 2429
        goto cleanup;
    }

2430
    def = privdom->def;
C
Cole Robinson 已提交
2431 2432

    if (gettimeofday(&tv, NULL) < 0) {
2433
        virReportSystemError(errno,
C
Cole Robinson 已提交
2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444
                             "%s", _("getting time of day"));
        goto cleanup;
    }

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

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

2445 2446 2447 2448 2449
    if (!(allcpumap = virBitmapNew(hostcpus)))
        goto cleanup;

    virBitmapSetAll(allcpumap);

C
Cole Robinson 已提交
2450
    /* Clamp to actual number of vcpus */
2451 2452
    if (maxinfo > virDomainDefGetVcpus(privdom->def))
        maxinfo = virDomainDefGetVcpus(privdom->def);
C
Cole Robinson 已提交
2453

2454 2455
    memset(info, 0, sizeof(*info) * maxinfo);
    memset(cpumaps, 0, maxinfo * maplen);
C
Cole Robinson 已提交
2456

2457
    for (i = 0; i < maxinfo; i++) {
2458
        virDomainVcpuInfoPtr vcpu = virDomainDefGetVcpu(def, i);
2459
        virBitmapPtr bitmap = NULL;
C
Cole Robinson 已提交
2460

2461 2462
        if (!vcpu->online)
            continue;
C
Cole Robinson 已提交
2463

2464 2465
        if (vcpu->cpumask)
            bitmap = vcpu->cpumask;
2466 2467 2468 2469
        else if (def->cpumask)
            bitmap = def->cpumask;
        else
            bitmap = allcpumap;
C
Cole Robinson 已提交
2470

2471 2472
        if (cpumaps)
            virBitmapToDataBuf(bitmap, VIR_GET_CPUMAP(cpumaps, maplen, i), maplen);
C
Cole Robinson 已提交
2473

2474 2475 2476
        info[i].number = i;
        info[i].state = VIR_VCPU_RUNNING;
        info[i].cpu = virBitmapLastSetBit(bitmap);
C
Cole Robinson 已提交
2477

2478 2479
        /* Fake an increasing cpu time value */
        info[i].cpuTime = statbase / 10;
C
Cole Robinson 已提交
2480 2481 2482
    }

    ret = maxinfo;
2483
 cleanup:
2484
    virBitmapFree(allcpumap);
2485
    virDomainObjEndAPI(&privdom);
C
Cole Robinson 已提交
2486 2487 2488
    return ret;
}

C
Cole Robinson 已提交
2489 2490 2491 2492 2493
static int testDomainPinVcpu(virDomainPtr domain,
                             unsigned int vcpu,
                             unsigned char *cpumap,
                             int maplen)
{
2494
    virDomainVcpuInfoPtr vcpuinfo;
C
Cole Robinson 已提交
2495
    virDomainObjPtr privdom;
2496
    virDomainDefPtr def;
C
Cole Robinson 已提交
2497 2498
    int ret = -1;

2499 2500
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
C
Cole Robinson 已提交
2501

2502 2503
    def = privdom->def;

C
Cole Robinson 已提交
2504
    if (!virDomainObjIsActive(privdom)) {
2505
        virReportError(VIR_ERR_OPERATION_INVALID,
2506
                       "%s", _("cannot pin vcpus on an inactive domain"));
C
Cole Robinson 已提交
2507 2508 2509
        goto cleanup;
    }

2510 2511
    if (!(vcpuinfo = virDomainDefGetVcpu(def, vcpu)) ||
        !vcpuinfo->online) {
2512 2513 2514
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested vcpu '%d' is not present in the domain"),
                       vcpu);
C
Cole Robinson 已提交
2515 2516 2517
        goto cleanup;
    }

2518 2519 2520
    virBitmapFree(vcpuinfo->cpumask);

    if (!(vcpuinfo->cpumask = virBitmapNewData(cpumap, maplen)))
2521
        goto cleanup;
C
Cole Robinson 已提交
2522 2523

    ret = 0;
2524

2525
 cleanup:
2526
    virDomainObjEndAPI(&privdom);
C
Cole Robinson 已提交
2527 2528 2529
    return ret;
}

2530 2531 2532 2533 2534 2535 2536
static int
testDomainGetVcpuPinInfo(virDomainPtr dom,
                        int ncpumaps,
                        unsigned char *cpumaps,
                        int maplen,
                        unsigned int flags)
{
2537
    testDriverPtr driver = dom->conn->privateData;
2538 2539
    virDomainObjPtr privdom;
    virDomainDefPtr def;
2540
    int ret = -1;
2541 2542 2543 2544 2545 2546 2547

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

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

2548 2549 2550
    ret = virDomainDefGetVcpuPinInfoHelper(def, maplen, ncpumaps, cpumaps,
                                           VIR_NODEINFO_MAXCPUS(driver->nodeInfo),
                                           NULL);
2551 2552 2553 2554 2555 2556

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

2557
static char *testDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
2558
{
2559
    testDriverPtr privconn = domain->conn->privateData;
2560
    virDomainDefPtr def;
2561
    virDomainObjPtr privdom;
2562 2563
    char *ret = NULL;

2564 2565
    /* Flags checked by virDomainDefFormat */

2566 2567
    if (!(privdom = testDomObjFromDomain(domain)))
        return NULL;
2568

2569 2570
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
2571

2572 2573
    ret = virDomainDefFormat(def, privconn->caps,
                             virDomainDefFormatConvertXMLFlags(flags));
2574

2575
    virDomainObjEndAPI(&privdom);
2576
    return ret;
2577
}
2578

2579 2580
static int testConnectNumOfDefinedDomains(virConnectPtr conn)
{
2581
    testDriverPtr privconn = conn->privateData;
2582

2583
    return virDomainObjListNumOfDomains(privconn->domains, false, NULL, NULL);
2584 2585
}

2586 2587
static int testConnectListDefinedDomains(virConnectPtr conn,
                                         char **const names,
2588 2589
                                         int maxnames)
{
2590

2591
    testDriverPtr privconn = conn->privateData;
2592 2593

    memset(names, 0, sizeof(*names)*maxnames);
2594 2595
    return virDomainObjListGetInactiveNames(privconn->domains, names, maxnames,
                                            NULL, NULL);
2596 2597
}

2598 2599 2600
static virDomainPtr testDomainDefineXMLFlags(virConnectPtr conn,
                                             const char *xml,
                                             unsigned int flags)
2601
{
2602
    testDriverPtr privconn = conn->privateData;
2603
    virDomainPtr ret = NULL;
2604
    virDomainDefPtr def;
2605
    virDomainObjPtr dom = NULL;
2606
    virObjectEventPtr event = NULL;
2607
    virDomainDefPtr oldDef = NULL;
2608 2609 2610
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;

    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
2611

2612
    if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
2613
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
2614

2615
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
2616
                                       parse_flags)) == NULL)
2617
        goto cleanup;
2618

2619
    if (testDomainGenerateIfnames(def) < 0)
2620
        goto cleanup;
2621
    if (!(dom = virDomainObjListAdd(privconn->domains,
2622
                                    def,
2623
                                    privconn->xmlopt,
2624 2625
                                    0,
                                    &oldDef)))
2626
        goto cleanup;
2627
    def = NULL;
2628
    dom->persistent = 1;
2629

2630
    event = virDomainEventLifecycleNewFromObj(dom,
2631
                                     VIR_DOMAIN_EVENT_DEFINED,
2632
                                     !oldDef ?
2633 2634
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
2635

2636
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
2637
    if (ret)
2638
        ret->id = dom->def->id;
2639

2640
 cleanup:
2641
    virDomainDefFree(def);
2642
    virDomainDefFree(oldDef);
2643
    if (dom)
2644
        virObjectUnlock(dom);
2645
    testObjectEventQueue(privconn, event);
2646
    return ret;
2647 2648
}

2649 2650 2651 2652 2653 2654
static virDomainPtr
testDomainDefineXML(virConnectPtr conn, const char *xml)
{
    return testDomainDefineXMLFlags(conn, xml, 0);
}

2655 2656 2657 2658 2659
static char *testDomainGetMetadata(virDomainPtr dom,
                                   int type,
                                   const char *uri,
                                   unsigned int flags)
{
2660
    testDriverPtr privconn = dom->conn->privateData;
2661
    virDomainObjPtr privdom;
2662
    char *ret;
2663 2664 2665 2666

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, NULL);

2667 2668
    if (!(privdom = testDomObjFromDomain(dom)))
        return NULL;
2669 2670 2671 2672

    ret = virDomainObjGetMetadata(privdom, type, uri, privconn->caps,
                                  privconn->xmlopt, flags);

2673
    virDomainObjEndAPI(&privdom);
2674 2675 2676 2677 2678 2679 2680 2681 2682 2683
    return ret;
}

static int testDomainSetMetadata(virDomainPtr dom,
                                 int type,
                                 const char *metadata,
                                 const char *key,
                                 const char *uri,
                                 unsigned int flags)
{
2684
    testDriverPtr privconn = dom->conn->privateData;
2685
    virDomainObjPtr privdom;
2686
    int ret;
2687 2688 2689 2690

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

2691 2692
    if (!(privdom = testDomObjFromDomain(dom)))
        return -1;
2693 2694 2695

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

2698
    virDomainObjEndAPI(&privdom);
2699 2700 2701 2702
    return ret;
}


2703 2704
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
2705 2706
                                      int startCell, int maxCells)
{
2707
    testDriverPtr privconn = conn->privateData;
2708 2709
    int cell;
    size_t i;
2710
    int ret = -1;
2711

2712
    testDriverLock(privconn);
2713
    if (startCell > privconn->numCells) {
2714 2715
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("Range exceeds available cells"));
2716
        goto cleanup;
2717 2718
    }

2719 2720 2721 2722
    for (cell = startCell, i = 0;
         (cell < privconn->numCells && i < maxCells);
         ++cell, ++i) {
        freemems[i] = privconn->cells[cell].mem;
2723
    }
2724
    ret = i;
2725

2726
 cleanup:
2727
    testDriverUnlock(privconn);
2728
    return ret;
2729 2730 2731
}


2732 2733
static int testDomainCreateWithFlags(virDomainPtr domain, unsigned int flags)
{
2734
    testDriverPtr privconn = domain->conn->privateData;
2735
    virDomainObjPtr privdom;
2736
    virObjectEventPtr event = NULL;
2737
    int ret = -1;
2738

2739 2740
    virCheckFlags(0, -1);

2741
    testDriverLock(privconn);
2742

2743
    if (!(privdom = testDomObjFromDomain(domain)))
2744
        goto cleanup;
2745

J
Jiri Denemark 已提交
2746
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_SHUTOFF) {
2747 2748
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Domain '%s' is already running"), domain->name);
2749
        goto cleanup;
2750 2751
    }

2752
    if (testDomainStartState(privconn, privdom,
J
Jiri Denemark 已提交
2753
                             VIR_DOMAIN_RUNNING_BOOTED) < 0)
2754 2755 2756
        goto cleanup;
    domain->id = privdom->def->id;

2757
    event = virDomainEventLifecycleNewFromObj(privdom,
2758 2759
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
2760
    ret = 0;
2761

2762
 cleanup:
2763
    virDomainObjEndAPI(&privdom);
2764
    testObjectEventQueue(privconn, event);
2765
    testDriverUnlock(privconn);
2766
    return ret;
2767 2768
}

2769 2770
static int testDomainCreate(virDomainPtr domain)
{
2771 2772 2773
    return testDomainCreateWithFlags(domain, 0);
}

2774 2775 2776
static int testDomainUndefineFlags(virDomainPtr domain,
                                   unsigned int flags)
{
2777
    testDriverPtr privconn = domain->conn->privateData;
2778
    virDomainObjPtr privdom;
2779
    virObjectEventPtr event = NULL;
2780
    int nsnapshots;
2781
    int ret = -1;
2782

2783 2784
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
                  VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
2785

2786

2787
    if (!(privdom = testDomObjFromDomain(domain)))
2788
        goto cleanup;
2789

C
Cole Robinson 已提交
2790 2791 2792 2793 2794 2795 2796 2797
    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;
    }

2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815
    /* 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. */
    }

2816
    event = virDomainEventLifecycleNewFromObj(privdom,
2817 2818
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
C
Cole Robinson 已提交
2819 2820
    privdom->hasManagedSave = false;

2821
    if (virDomainObjIsActive(privdom))
2822
        privdom->persistent = 0;
2823 2824
    else
        virDomainObjListRemove(privconn->domains, privdom);
2825

2826
    ret = 0;
2827

2828
 cleanup:
2829
    virDomainObjEndAPI(&privdom);
2830
    testObjectEventQueue(privconn, event);
2831
    return ret;
2832 2833
}

2834 2835 2836 2837 2838
static int testDomainUndefine(virDomainPtr domain)
{
    return testDomainUndefineFlags(domain, 0);
}

2839 2840 2841
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
2842 2843
    virDomainObjPtr privdom;

2844 2845
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2846

2847
    *autostart = privdom->autostart;
2848

2849
    virDomainObjEndAPI(&privdom);
2850
    return 0;
2851 2852 2853 2854 2855 2856
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
2857 2858
    virDomainObjPtr privdom;

2859 2860
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2861

2862
    privdom->autostart = autostart ? 1 : 0;
2863

2864
    virDomainObjEndAPI(&privdom);
2865
    return 0;
2866
}
2867

2868
static char *testDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED,
2869 2870
                                        int *nparams)
{
2871 2872
    char *type = NULL;

2873 2874 2875
    if (nparams)
        *nparams = 1;

2876
    ignore_value(VIR_STRDUP(type, "fair"));
2877

2878 2879 2880
    return type;
}

2881
static int
2882 2883 2884 2885
testDomainGetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int *nparams,
                                      unsigned int flags)
2886
{
2887
    virDomainObjPtr privdom;
2888
    int ret = -1;
2889

2890 2891
    virCheckFlags(0, -1);

2892 2893
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2894

2895 2896
    if (virTypedParameterAssign(params, VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, 50) < 0)
2897
        goto cleanup;
2898 2899
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
2900 2901

    *nparams = 1;
2902 2903
    ret = 0;

2904
 cleanup:
2905
    virDomainObjEndAPI(&privdom);
2906
    return ret;
2907
}
2908

2909
static int
2910 2911 2912
testDomainGetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int *nparams)
2913
{
2914
    return testDomainGetSchedulerParametersFlags(domain, params, nparams, 0);
2915
}
2916

2917
static int
2918 2919 2920 2921
testDomainSetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int nparams,
                                      unsigned int flags)
2922
{
2923
    virDomainObjPtr privdom;
2924 2925
    int ret = -1;
    size_t i;
2926

2927
    virCheckFlags(0, -1);
2928 2929 2930 2931
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
2932
        return -1;
2933

2934 2935
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2936

2937
    for (i = 0; i < nparams; i++) {
2938 2939 2940
        if (STREQ(params[i].field, VIR_DOMAIN_SCHEDULER_WEIGHT)) {
            /* XXX */
            /*privdom->weight = params[i].value.ui;*/
2941
        }
2942
    }
2943

2944 2945
    ret = 0;

2946
    virDomainObjEndAPI(&privdom);
2947
    return ret;
2948 2949
}

2950
static int
2951 2952 2953
testDomainSetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int nparams)
2954
{
2955
    return testDomainSetSchedulerParametersFlags(domain, params, nparams, 0);
2956 2957
}

2958 2959
static int testDomainBlockStats(virDomainPtr domain,
                                const char *path,
2960
                                virDomainBlockStatsPtr stats)
2961 2962 2963 2964
{
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
2965
    int ret = -1;
2966

2967 2968 2969 2970 2971 2972
    if (!*path) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("summary statistics are not supported yet"));
        return ret;
    }

2973 2974
    if (!(privdom = testDomObjFromDomain(domain)))
        return ret;
2975

2976
    if (virDomainDiskIndexByName(privdom->def, path, false) < 0) {
2977 2978
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path: %s"), path);
2979 2980 2981 2982
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
2983
        virReportSystemError(errno,
2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996
                             "%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;
2997
 error:
2998
    virDomainObjEndAPI(&privdom);
2999 3000 3001 3002 3003
    return ret;
}

static int testDomainInterfaceStats(virDomainPtr domain,
                                    const char *path,
3004
                                    virDomainInterfaceStatsPtr stats)
3005 3006 3007 3008
{
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
3009 3010
    size_t i;
    int found = 0, ret = -1;
3011

3012 3013
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3014

3015
    for (i = 0; i < privdom->def->nnets; i++) {
3016
        if (privdom->def->nets[i]->ifname &&
3017
            STREQ(privdom->def->nets[i]->ifname, path)) {
3018 3019 3020 3021 3022 3023
            found = 1;
            break;
        }
    }

    if (!found) {
3024 3025
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path, '%s' is not a known interface"), path);
3026 3027 3028 3029
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
3030
        virReportSystemError(errno,
3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046
                             "%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;
3047
 error:
3048
    virDomainObjEndAPI(&privdom);
3049 3050 3051
    return ret;
}

3052

3053 3054
static virNetworkPtr testNetworkLookupByUUID(virConnectPtr conn,
                                             const unsigned char *uuid)
3055
{
3056
    testDriverPtr privconn = conn->privateData;
3057
    virNetworkObjPtr net;
3058
    virNetworkPtr ret = NULL;
3059

3060
    net = virNetworkObjFindByUUID(privconn->networks, uuid);
3061
    if (net == NULL) {
3062
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3063
        goto cleanup;
3064 3065
    }

3066 3067
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

3068
 cleanup:
3069
    virNetworkObjEndAPI(&net);
3070
    return ret;
3071
}
3072

3073
static virNetworkPtr testNetworkLookupByName(virConnectPtr conn,
3074
                                             const char *name)
3075
{
3076
    testDriverPtr privconn = conn->privateData;
3077 3078
    virNetworkObjPtr net;
    virNetworkPtr ret = NULL;
3079

3080
    net = virNetworkObjFindByName(privconn->networks, name);
3081
    if (net == NULL) {
3082
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3083
        goto cleanup;
3084 3085
    }

3086 3087
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

3088
 cleanup:
3089
    virNetworkObjEndAPI(&net);
3090
    return ret;
3091 3092 3093
}


3094 3095
static int testConnectNumOfNetworks(virConnectPtr conn)
{
3096
    testDriverPtr privconn = conn->privateData;
3097
    int numActive;
3098

3099 3100
    numActive = virNetworkObjListNumOfNetworks(privconn->networks,
                                               true, NULL, conn);
3101
    return numActive;
3102 3103
}

3104
static int testConnectListNetworks(virConnectPtr conn, char **const names, int nnames) {
3105
    testDriverPtr privconn = conn->privateData;
3106
    int n;
3107

3108 3109
    n = virNetworkObjListGetNames(privconn->networks,
                                  true, names, nnames, NULL, conn);
3110
    return n;
3111 3112
}

3113 3114
static int testConnectNumOfDefinedNetworks(virConnectPtr conn)
{
3115
    testDriverPtr privconn = conn->privateData;
3116
    int numInactive;
3117

3118 3119
    numInactive = virNetworkObjListNumOfNetworks(privconn->networks,
                                                 false, NULL, conn);
3120
    return numInactive;
3121 3122
}

3123
static int testConnectListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
3124
    testDriverPtr privconn = conn->privateData;
3125
    int n;
3126

3127 3128
    n = virNetworkObjListGetNames(privconn->networks,
                                  false, names, nnames, NULL, conn);
3129
    return n;
3130 3131
}

3132
static int
3133
testConnectListAllNetworks(virConnectPtr conn,
3134 3135 3136
                           virNetworkPtr **nets,
                           unsigned int flags)
{
3137
    testDriverPtr privconn = conn->privateData;
3138 3139 3140

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

3141
    return virNetworkObjListExport(conn, privconn->networks, nets, NULL, flags);
3142
}
3143 3144 3145

static int testNetworkIsActive(virNetworkPtr net)
{
3146
    testDriverPtr privconn = net->conn->privateData;
3147 3148 3149
    virNetworkObjPtr obj;
    int ret = -1;

3150
    obj = virNetworkObjFindByUUID(privconn->networks, net->uuid);
3151
    if (!obj) {
3152
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3153 3154 3155 3156
        goto cleanup;
    }
    ret = virNetworkObjIsActive(obj);

3157
 cleanup:
3158
    virNetworkObjEndAPI(&obj);
3159 3160 3161 3162 3163
    return ret;
}

static int testNetworkIsPersistent(virNetworkPtr net)
{
3164
    testDriverPtr privconn = net->conn->privateData;
3165 3166 3167
    virNetworkObjPtr obj;
    int ret = -1;

3168
    obj = virNetworkObjFindByUUID(privconn->networks, net->uuid);
3169
    if (!obj) {
3170
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3171 3172 3173 3174
        goto cleanup;
    }
    ret = obj->persistent;

3175
 cleanup:
3176
    virNetworkObjEndAPI(&obj);
3177 3178 3179 3180
    return ret;
}


3181 3182
static virNetworkPtr testNetworkCreateXML(virConnectPtr conn, const char *xml)
{
3183
    testDriverPtr privconn = conn->privateData;
3184
    virNetworkDefPtr def;
3185
    virNetworkObjPtr net = NULL;
3186
    virNetworkPtr ret = NULL;
3187
    virObjectEventPtr event = NULL;
3188

3189
    if ((def = virNetworkDefParseString(xml)) == NULL)
3190
        goto cleanup;
3191

3192 3193 3194
    if (!(net = virNetworkAssignDef(privconn->networks, def,
                                    VIR_NETWORK_OBJ_LIST_ADD_LIVE |
                                    VIR_NETWORK_OBJ_LIST_ADD_CHECK_LIVE)))
3195 3196
        goto cleanup;
    def = NULL;
3197
    net->active = 1;
3198

3199
    event = virNetworkEventLifecycleNew(net->def->name, net->def->uuid,
3200 3201
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3202

3203
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3204

3205
 cleanup:
3206
    virNetworkDefFree(def);
3207
    testObjectEventQueue(privconn, event);
3208
    virNetworkObjEndAPI(&net);
3209
    return ret;
3210 3211
}

3212
static
3213
virNetworkPtr testNetworkDefineXML(virConnectPtr conn, const char *xml)
3214
{
3215
    testDriverPtr privconn = conn->privateData;
3216
    virNetworkDefPtr def;
3217
    virNetworkObjPtr net = NULL;
3218
    virNetworkPtr ret = NULL;
3219
    virObjectEventPtr event = NULL;
3220

3221
    if ((def = virNetworkDefParseString(xml)) == NULL)
3222
        goto cleanup;
3223

3224
    if (!(net = virNetworkAssignDef(privconn->networks, def, 0)))
3225 3226
        goto cleanup;
    def = NULL;
3227

3228
    event = virNetworkEventLifecycleNew(net->def->name, net->def->uuid,
3229 3230
                                        VIR_NETWORK_EVENT_DEFINED,
                                        0);
3231

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

3234
 cleanup:
3235
    virNetworkDefFree(def);
3236
    testObjectEventQueue(privconn, event);
3237
    virNetworkObjEndAPI(&net);
3238
    return ret;
3239 3240
}

3241 3242
static int testNetworkUndefine(virNetworkPtr network)
{
3243
    testDriverPtr privconn = network->conn->privateData;
3244
    virNetworkObjPtr privnet;
3245
    int ret = -1;
3246
    virObjectEventPtr event = NULL;
3247

3248
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3249 3250

    if (privnet == NULL) {
3251
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3252
        goto cleanup;
3253
    }
3254

D
Daniel P. Berrange 已提交
3255
    if (virNetworkObjIsActive(privnet)) {
3256 3257
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is still running"), network->name);
3258
        goto cleanup;
3259 3260
    }

3261
    event = virNetworkEventLifecycleNew(network->name, network->uuid,
3262 3263
                                        VIR_NETWORK_EVENT_UNDEFINED,
                                        0);
3264

3265
    virNetworkRemoveInactive(privconn->networks, privnet);
3266
    ret = 0;
3267

3268
 cleanup:
3269
    testObjectEventQueue(privconn, event);
3270
    virNetworkObjEndAPI(&privnet);
3271
    return ret;
3272 3273
}

3274 3275 3276 3277 3278 3279 3280 3281
static int
testNetworkUpdate(virNetworkPtr net,
                  unsigned int command,
                  unsigned int section,
                  int parentIndex,
                  const char *xml,
                  unsigned int flags)
{
3282
    testDriverPtr privconn = net->conn->privateData;
3283 3284 3285 3286 3287 3288 3289
    virNetworkObjPtr network = NULL;
    int isActive, ret = -1;

    virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
                  VIR_NETWORK_UPDATE_AFFECT_CONFIG,
                  -1);

3290
    network = virNetworkObjFindByUUID(privconn->networks, net->uuid);
3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314
    if (!network) {
        virReportError(VIR_ERR_NO_NETWORK,
                       "%s", _("no network with matching uuid"));
        goto cleanup;
    }

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

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

    ret = 0;
3315
 cleanup:
3316
    virNetworkObjEndAPI(&network);
3317 3318 3319
    return ret;
}

3320 3321
static int testNetworkCreate(virNetworkPtr network)
{
3322
    testDriverPtr privconn = network->conn->privateData;
3323
    virNetworkObjPtr privnet;
3324
    int ret = -1;
3325
    virObjectEventPtr event = NULL;
3326

3327
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3328
    if (privnet == NULL) {
3329
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3330
        goto cleanup;
3331
    }
3332

D
Daniel P. Berrange 已提交
3333
    if (virNetworkObjIsActive(privnet)) {
3334 3335
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is already running"), network->name);
3336
        goto cleanup;
3337 3338
    }

3339
    privnet->active = 1;
3340
    event = virNetworkEventLifecycleNew(privnet->def->name, privnet->def->uuid,
3341 3342
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3343
    ret = 0;
3344

3345
 cleanup:
3346
    testObjectEventQueue(privconn, event);
3347
    virNetworkObjEndAPI(&privnet);
3348
    return ret;
3349 3350
}

3351 3352
static int testNetworkDestroy(virNetworkPtr network)
{
3353
    testDriverPtr privconn = network->conn->privateData;
3354
    virNetworkObjPtr privnet;
3355
    int ret = -1;
3356
    virObjectEventPtr event = NULL;
3357

3358
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3359
    if (privnet == NULL) {
3360
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3361
        goto cleanup;
3362
    }
3363

3364
    privnet->active = 0;
3365
    event = virNetworkEventLifecycleNew(privnet->def->name, privnet->def->uuid,
3366 3367
                                        VIR_NETWORK_EVENT_STOPPED,
                                        0);
3368
    if (!privnet->persistent)
3369
        virNetworkRemoveInactive(privconn->networks, privnet);
3370

3371 3372
    ret = 0;

3373
 cleanup:
3374
    testObjectEventQueue(privconn, event);
3375
    virNetworkObjEndAPI(&privnet);
3376
    return ret;
3377 3378
}

3379
static char *testNetworkGetXMLDesc(virNetworkPtr network,
E
Eric Blake 已提交
3380
                                   unsigned int flags)
3381
{
3382
    testDriverPtr privconn = network->conn->privateData;
3383
    virNetworkObjPtr privnet;
3384
    char *ret = NULL;
3385

E
Eric Blake 已提交
3386 3387
    virCheckFlags(0, NULL);

3388
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3389
    if (privnet == NULL) {
3390
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3391
        goto cleanup;
3392
    }
3393

3394
    ret = virNetworkDefFormat(privnet->def, flags);
3395

3396
 cleanup:
3397
    virNetworkObjEndAPI(&privnet);
3398
    return ret;
3399 3400 3401
}

static char *testNetworkGetBridgeName(virNetworkPtr network) {
3402
    testDriverPtr privconn = network->conn->privateData;
3403
    char *bridge = NULL;
3404 3405
    virNetworkObjPtr privnet;

3406
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3407
    if (privnet == NULL) {
3408
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3409
        goto cleanup;
3410 3411
    }

3412
    if (!(privnet->def->bridge)) {
3413 3414 3415
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("network '%s' does not have a bridge name."),
                       privnet->def->name);
3416 3417 3418
        goto cleanup;
    }

3419
    ignore_value(VIR_STRDUP(bridge, privnet->def->bridge));
3420

3421
 cleanup:
3422
    virNetworkObjEndAPI(&privnet);
3423 3424 3425 3426
    return bridge;
}

static int testNetworkGetAutostart(virNetworkPtr network,
3427 3428
                                   int *autostart)
{
3429
    testDriverPtr privconn = network->conn->privateData;
3430
    virNetworkObjPtr privnet;
3431
    int ret = -1;
3432

3433
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3434
    if (privnet == NULL) {
3435
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3436
        goto cleanup;
3437 3438
    }

3439
    *autostart = privnet->autostart;
3440 3441
    ret = 0;

3442
 cleanup:
3443
    virNetworkObjEndAPI(&privnet);
3444
    return ret;
3445 3446 3447
}

static int testNetworkSetAutostart(virNetworkPtr network,
3448 3449
                                   int autostart)
{
3450
    testDriverPtr privconn = network->conn->privateData;
3451
    virNetworkObjPtr privnet;
3452
    int ret = -1;
3453

3454
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3455
    if (privnet == NULL) {
3456
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3457
        goto cleanup;
3458 3459
    }

3460
    privnet->autostart = autostart ? 1 : 0;
3461 3462
    ret = 0;

3463
 cleanup:
3464
    virNetworkObjEndAPI(&privnet);
3465
    return ret;
3466
}
3467

C
Cole Robinson 已提交
3468

L
Laine Stump 已提交
3469 3470 3471 3472 3473
/*
 * Physical host interface routines
 */


3474
static int testConnectNumOfInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3475
{
3476
    testDriverPtr privconn = conn->privateData;
3477 3478
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3479 3480

    testDriverLock(privconn);
3481
    for (i = 0; (i < privconn->ifaces.count); i++) {
L
Laine Stump 已提交
3482
        virInterfaceObjLock(privconn->ifaces.objs[i]);
3483
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i]))
L
Laine Stump 已提交
3484 3485 3486 3487 3488 3489 3490
            count++;
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3491
static int testConnectListInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3492
{
3493
    testDriverPtr privconn = conn->privateData;
3494 3495
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3496 3497 3498

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
3499
    for (i = 0; (i < privconn->ifaces.count) && (n < nnames); i++) {
L
Laine Stump 已提交
3500
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3501
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
3502
            if (VIR_STRDUP(names[n++], privconn->ifaces.objs[i]->def->name) < 0) {
L
Laine Stump 已提交
3503
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
3504
                goto error;
L
Laine Stump 已提交
3505 3506 3507 3508 3509 3510 3511 3512
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

3513
 error:
3514
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3515 3516 3517 3518 3519
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

3520
static int testConnectNumOfDefinedInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3521
{
3522
    testDriverPtr privconn = conn->privateData;
3523 3524
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3525 3526

    testDriverLock(privconn);
3527
    for (i = 0; i < privconn->ifaces.count; i++) {
L
Laine Stump 已提交
3528
        virInterfaceObjLock(privconn->ifaces.objs[i]);
3529
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i]))
L
Laine Stump 已提交
3530 3531 3532 3533 3534 3535 3536
            count++;
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3537
static int testConnectListDefinedInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3538
{
3539
    testDriverPtr privconn = conn->privateData;
3540 3541
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3542 3543 3544

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
3545
    for (i = 0; (i < privconn->ifaces.count) && (n < nnames); i++) {
L
Laine Stump 已提交
3546
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3547
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
3548
            if (VIR_STRDUP(names[n++], privconn->ifaces.objs[i]->def->name) < 0) {
L
Laine Stump 已提交
3549
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
3550
                goto error;
L
Laine Stump 已提交
3551 3552 3553 3554 3555 3556 3557 3558
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

3559
 error:
3560
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3561 3562 3563 3564 3565
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

3566
static virInterfacePtr testInterfaceLookupByName(virConnectPtr conn,
L
Laine Stump 已提交
3567 3568
                                                 const char *name)
{
3569
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3570 3571 3572 3573 3574 3575 3576 3577
    virInterfaceObjPtr iface;
    virInterfacePtr ret = NULL;

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

    if (iface == NULL) {
3578
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3579 3580 3581 3582 3583
        goto cleanup;
    }

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

3584
 cleanup:
L
Laine Stump 已提交
3585 3586 3587 3588 3589
    if (iface)
        virInterfaceObjUnlock(iface);
    return ret;
}

3590
static virInterfacePtr testInterfaceLookupByMACString(virConnectPtr conn,
L
Laine Stump 已提交
3591 3592
                                                      const char *mac)
{
3593
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3594 3595 3596 3597 3598 3599 3600 3601 3602
    virInterfaceObjPtr iface;
    int ifacect;
    virInterfacePtr ret = NULL;

    testDriverLock(privconn);
    ifacect = virInterfaceFindByMACString(&privconn->ifaces, mac, &iface, 1);
    testDriverUnlock(privconn);

    if (ifacect == 0) {
3603
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3604 3605 3606 3607
        goto cleanup;
    }

    if (ifacect > 1) {
3608
        virReportError(VIR_ERR_MULTIPLE_INTERFACES, NULL);
L
Laine Stump 已提交
3609 3610 3611 3612 3613
        goto cleanup;
    }

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

3614
 cleanup:
L
Laine Stump 已提交
3615 3616 3617 3618 3619
    if (iface)
        virInterfaceObjUnlock(iface);
    return ret;
}

3620 3621
static int testInterfaceIsActive(virInterfacePtr iface)
{
3622
    testDriverPtr privconn = iface->conn->privateData;
3623 3624 3625 3626 3627 3628 3629
    virInterfaceObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virInterfaceFindByName(&privconn->ifaces, iface->name);
    testDriverUnlock(privconn);
    if (!obj) {
3630
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
3631 3632 3633 3634
        goto cleanup;
    }
    ret = virInterfaceObjIsActive(obj);

3635
 cleanup:
3636 3637 3638 3639 3640
    if (obj)
        virInterfaceObjUnlock(obj);
    return ret;
}

3641
static int testInterfaceChangeBegin(virConnectPtr conn,
E
Eric Blake 已提交
3642
                                    unsigned int flags)
3643
{
3644
    testDriverPtr privconn = conn->privateData;
3645 3646
    int ret = -1;

E
Eric Blake 已提交
3647 3648
    virCheckFlags(0, -1);

3649 3650
    testDriverLock(privconn);
    if (privconn->transaction_running) {
3651
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3652
                       _("there is another transaction running."));
3653 3654 3655 3656 3657 3658 3659 3660 3661 3662
        goto cleanup;
    }

    privconn->transaction_running = true;

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

    ret = 0;
3663
 cleanup:
3664 3665 3666 3667 3668
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceChangeCommit(virConnectPtr conn,
E
Eric Blake 已提交
3669
                                     unsigned int flags)
3670
{
3671
    testDriverPtr privconn = conn->privateData;
3672 3673
    int ret = -1;

E
Eric Blake 已提交
3674 3675
    virCheckFlags(0, -1);

3676 3677 3678
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3679
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3680 3681
                       _("no transaction running, "
                         "nothing to be committed."));
3682 3683 3684 3685 3686 3687 3688 3689
        goto cleanup;
    }

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

    ret = 0;

3690
 cleanup:
3691 3692 3693 3694 3695 3696
    testDriverUnlock(privconn);

    return ret;
}

static int testInterfaceChangeRollback(virConnectPtr conn,
E
Eric Blake 已提交
3697
                                       unsigned int flags)
3698
{
3699
    testDriverPtr privconn = conn->privateData;
3700 3701
    int ret = -1;

E
Eric Blake 已提交
3702 3703
    virCheckFlags(0, -1);

3704 3705 3706
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3707
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3708 3709
                       _("no transaction running, "
                         "nothing to rollback."));
3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722
        goto cleanup;
    }

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

    privconn->transaction_running = false;

    ret = 0;

3723
 cleanup:
3724 3725 3726
    testDriverUnlock(privconn);
    return ret;
}
3727

L
Laine Stump 已提交
3728
static char *testInterfaceGetXMLDesc(virInterfacePtr iface,
E
Eric Blake 已提交
3729
                                     unsigned int flags)
L
Laine Stump 已提交
3730
{
3731
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3732 3733 3734
    virInterfaceObjPtr privinterface;
    char *ret = NULL;

E
Eric Blake 已提交
3735 3736
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
3737 3738 3739 3740 3741 3742
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);
    testDriverUnlock(privconn);

    if (privinterface == NULL) {
3743
        virReportError(VIR_ERR_NO_INTERFACE, __FUNCTION__);
L
Laine Stump 已提交
3744 3745 3746
        goto cleanup;
    }

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

3749
 cleanup:
L
Laine Stump 已提交
3750 3751 3752 3753 3754 3755 3756
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    return ret;
}


static virInterfacePtr testInterfaceDefineXML(virConnectPtr conn, const char *xmlStr,
E
Eric Blake 已提交
3757
                                              unsigned int flags)
L
Laine Stump 已提交
3758
{
3759
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3760 3761 3762 3763
    virInterfaceDefPtr def;
    virInterfaceObjPtr iface = NULL;
    virInterfacePtr ret = NULL;

E
Eric Blake 已提交
3764 3765
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
3766
    testDriverLock(privconn);
3767
    if ((def = virInterfaceDefParseString(xmlStr)) == NULL)
L
Laine Stump 已提交
3768 3769
        goto cleanup;

3770
    if ((iface = virInterfaceAssignDef(&privconn->ifaces, def)) == NULL)
L
Laine Stump 已提交
3771 3772 3773 3774 3775
        goto cleanup;
    def = NULL;

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

3776
 cleanup:
L
Laine Stump 已提交
3777 3778 3779 3780 3781 3782 3783 3784 3785
    virInterfaceDefFree(def);
    if (iface)
        virInterfaceObjUnlock(iface);
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceUndefine(virInterfacePtr iface)
{
3786
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3787 3788 3789 3790 3791 3792 3793 3794
    virInterfaceObjPtr privinterface;
    int ret = -1;

    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);

    if (privinterface == NULL) {
3795
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3796 3797 3798 3799 3800 3801 3802
        goto cleanup;
    }

    virInterfaceRemove(&privconn->ifaces,
                       privinterface);
    ret = 0;

3803
 cleanup:
L
Laine Stump 已提交
3804 3805 3806 3807 3808
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceCreate(virInterfacePtr iface,
E
Eric Blake 已提交
3809
                               unsigned int flags)
L
Laine Stump 已提交
3810
{
3811
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3812 3813 3814
    virInterfaceObjPtr privinterface;
    int ret = -1;

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

L
Laine Stump 已提交
3817 3818 3819 3820 3821
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);

    if (privinterface == NULL) {
3822
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3823 3824 3825 3826
        goto cleanup;
    }

    if (privinterface->active != 0) {
3827
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
3828 3829 3830 3831 3832 3833
        goto cleanup;
    }

    privinterface->active = 1;
    ret = 0;

3834
 cleanup:
L
Laine Stump 已提交
3835 3836 3837 3838 3839 3840 3841
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceDestroy(virInterfacePtr iface,
E
Eric Blake 已提交
3842
                                unsigned int flags)
L
Laine Stump 已提交
3843
{
3844
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3845 3846 3847
    virInterfaceObjPtr privinterface;
    int ret = -1;

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

L
Laine Stump 已提交
3850 3851 3852 3853 3854
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);

    if (privinterface == NULL) {
3855
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3856 3857 3858 3859
        goto cleanup;
    }

    if (privinterface->active == 0) {
3860
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
3861 3862 3863 3864 3865 3866
        goto cleanup;
    }

    privinterface->active = 0;
    ret = 0;

3867
 cleanup:
L
Laine Stump 已提交
3868 3869 3870 3871 3872 3873 3874 3875
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    testDriverUnlock(privconn);
    return ret;
}



C
Cole Robinson 已提交
3876 3877 3878 3879
/*
 * Storage Driver routines
 */

3880

3881 3882
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool)
{
C
Cole Robinson 已提交
3883 3884 3885 3886 3887

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

3888
    return VIR_STRDUP(pool->configFile, "");
C
Cole Robinson 已提交
3889 3890
}

3891

C
Cole Robinson 已提交
3892 3893
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
3894 3895
                            const unsigned char *uuid)
{
3896
    testDriverPtr privconn = conn->privateData;
3897 3898
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3899

3900
    testDriverLock(privconn);
3901
    pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid);
3902
    testDriverUnlock(privconn);
3903 3904

    if (pool == NULL) {
3905
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
3906
        goto cleanup;
C
Cole Robinson 已提交
3907 3908
    }

3909 3910
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
3911

3912
 cleanup:
3913 3914
    if (pool)
        virStoragePoolObjUnlock(pool);
3915
    return ret;
C
Cole Robinson 已提交
3916 3917 3918 3919
}

static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
3920 3921
                            const char *name)
{
3922
    testDriverPtr privconn = conn->privateData;
3923 3924
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3925

3926
    testDriverLock(privconn);
3927
    pool = virStoragePoolObjFindByName(&privconn->pools, name);
3928
    testDriverUnlock(privconn);
3929 3930

    if (pool == NULL) {
3931
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
3932
        goto cleanup;
C
Cole Robinson 已提交
3933 3934
    }

3935 3936
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
3937

3938
 cleanup:
3939 3940
    if (pool)
        virStoragePoolObjUnlock(pool);
3941
    return ret;
C
Cole Robinson 已提交
3942 3943 3944
}

static virStoragePoolPtr
3945 3946
testStoragePoolLookupByVolume(virStorageVolPtr vol)
{
C
Cole Robinson 已提交
3947 3948 3949 3950
    return testStoragePoolLookupByName(vol->conn, vol->pool);
}

static int
3951 3952
testConnectNumOfStoragePools(virConnectPtr conn)
{
3953
    testDriverPtr privconn = conn->privateData;
3954 3955
    int numActive = 0;
    size_t i;
C
Cole Robinson 已提交
3956

3957
    testDriverLock(privconn);
3958
    for (i = 0; i < privconn->pools.count; i++)
C
Cole Robinson 已提交
3959 3960
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numActive++;
3961
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3962 3963 3964 3965 3966

    return numActive;
}

static int
3967 3968
testConnectListStoragePools(virConnectPtr conn,
                            char **const names,
3969 3970
                            int nnames)
{
3971
    testDriverPtr privconn = conn->privateData;
3972 3973
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
3974

3975
    testDriverLock(privconn);
C
Cole Robinson 已提交
3976
    memset(names, 0, sizeof(*names)*nnames);
3977
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
3978
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3979
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
3980
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
3981
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
3982
            goto error;
3983 3984 3985 3986
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3987 3988 3989

    return n;

3990
 error:
3991
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
3992
        VIR_FREE(names[n]);
3993
    testDriverUnlock(privconn);
3994
    return -1;
C
Cole Robinson 已提交
3995 3996 3997
}

static int
3998 3999
testConnectNumOfDefinedStoragePools(virConnectPtr conn)
{
4000
    testDriverPtr privconn = conn->privateData;
4001 4002
    int numInactive = 0;
    size_t i;
C
Cole Robinson 已提交
4003

4004
    testDriverLock(privconn);
4005
    for (i = 0; i < privconn->pools.count; i++) {
4006
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4007 4008
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numInactive++;
4009 4010 4011
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4012 4013 4014 4015 4016

    return numInactive;
}

static int
4017 4018
testConnectListDefinedStoragePools(virConnectPtr conn,
                                   char **const names,
4019 4020
                                   int nnames)
{
4021
    testDriverPtr privconn = conn->privateData;
4022 4023
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
4024

4025
    testDriverLock(privconn);
C
Cole Robinson 已提交
4026
    memset(names, 0, sizeof(*names)*nnames);
4027
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
4028
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4029
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
4030
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
4031
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
4032
            goto error;
4033 4034 4035 4036
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4037 4038 4039

    return n;

4040
 error:
4041
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
4042
        VIR_FREE(names[n]);
4043
    testDriverUnlock(privconn);
4044
    return -1;
C
Cole Robinson 已提交
4045 4046
}

4047
static int
4048 4049 4050
testConnectListAllStoragePools(virConnectPtr conn,
                               virStoragePoolPtr **pools,
                               unsigned int flags)
4051
{
4052
    testDriverPtr privconn = conn->privateData;
4053 4054 4055 4056 4057
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

    testDriverLock(privconn);
4058 4059
    ret = virStoragePoolObjListExport(conn, privconn->pools, pools,
                                      NULL, flags);
4060 4061 4062 4063
    testDriverUnlock(privconn);

    return ret;
}
C
Cole Robinson 已提交
4064

4065 4066
static int testStoragePoolIsActive(virStoragePoolPtr pool)
{
4067
    testDriverPtr privconn = pool->conn->privateData;
4068 4069 4070 4071 4072 4073 4074
    virStoragePoolObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virStoragePoolObjFindByUUID(&privconn->pools, pool->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
4075
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4076 4077 4078 4079
        goto cleanup;
    }
    ret = virStoragePoolObjIsActive(obj);

4080
 cleanup:
4081 4082 4083 4084 4085 4086 4087
    if (obj)
        virStoragePoolObjUnlock(obj);
    return ret;
}

static int testStoragePoolIsPersistent(virStoragePoolPtr pool)
{
4088
    testDriverPtr privconn = pool->conn->privateData;
4089 4090 4091 4092 4093 4094 4095
    virStoragePoolObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virStoragePoolObjFindByUUID(&privconn->pools, pool->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
4096
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4097 4098 4099 4100
        goto cleanup;
    }
    ret = obj->configFile ? 1 : 0;

4101
 cleanup:
4102 4103 4104 4105 4106 4107 4108
    if (obj)
        virStoragePoolObjUnlock(obj);
    return ret;
}



C
Cole Robinson 已提交
4109
static int
4110 4111
testStoragePoolCreate(virStoragePoolPtr pool,
                      unsigned int flags)
E
Eric Blake 已提交
4112
{
4113
    testDriverPtr privconn = pool->conn->privateData;
4114
    virStoragePoolObjPtr privpool;
4115
    int ret = -1;
4116

E
Eric Blake 已提交
4117 4118
    virCheckFlags(0, -1);

4119
    testDriverLock(privconn);
4120 4121
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4122
    testDriverUnlock(privconn);
4123 4124

    if (privpool == NULL) {
4125
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4126
        goto cleanup;
4127 4128
    }

4129
    if (virStoragePoolObjIsActive(privpool)) {
4130 4131
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4132 4133
        goto cleanup;
    }
C
Cole Robinson 已提交
4134 4135

    privpool->active = 1;
4136
    ret = 0;
C
Cole Robinson 已提交
4137

4138
 cleanup:
4139 4140
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4141
    return ret;
C
Cole Robinson 已提交
4142 4143 4144
}

static char *
4145 4146 4147 4148
testConnectFindStoragePoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type,
                                  const char *srcSpec,
                                  unsigned int flags)
C
Cole Robinson 已提交
4149
{
4150 4151 4152 4153
    virStoragePoolSourcePtr source = NULL;
    int pool_type;
    char *ret = NULL;

E
Eric Blake 已提交
4154 4155
    virCheckFlags(0, NULL);

4156 4157
    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
4158 4159
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
4160 4161 4162 4163
        goto cleanup;
    }

    if (srcSpec) {
4164
        source = virStoragePoolDefParseSourceString(srcSpec, pool_type);
4165 4166 4167 4168 4169 4170 4171
        if (!source)
            goto cleanup;
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
4172
        ignore_value(VIR_STRDUP(ret, defaultPoolSourcesLogicalXML));
4173 4174 4175
        break;

    case VIR_STORAGE_POOL_NETFS:
4176
        if (!source || !source->hosts[0].name) {
4177 4178
            virReportError(VIR_ERR_INVALID_ARG,
                           "%s", _("hostname must be specified for netfs sources"));
4179 4180 4181
            goto cleanup;
        }

4182 4183
        ignore_value(virAsprintf(&ret, defaultPoolSourcesNetFSXML,
                                 source->hosts[0].name));
4184 4185 4186
        break;

    default:
4187 4188
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source discovery"), type);
4189 4190
    }

4191
 cleanup:
4192 4193
    virStoragePoolSourceFree(source);
    return ret;
C
Cole Robinson 已提交
4194 4195 4196 4197
}


static virStoragePoolPtr
4198 4199 4200
testStoragePoolCreateXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4201
{
4202
    testDriverPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4203
    virStoragePoolDefPtr def;
4204
    virStoragePoolObjPtr pool = NULL;
4205
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4206

E
Eric Blake 已提交
4207 4208
    virCheckFlags(0, NULL);

4209
    testDriverLock(privconn);
4210
    if (!(def = virStoragePoolDefParseString(xml)))
4211
        goto cleanup;
C
Cole Robinson 已提交
4212

4213 4214 4215 4216
    pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid);
    if (!pool)
        pool = virStoragePoolObjFindByName(&privconn->pools, def->name);
    if (pool) {
4217 4218
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("storage pool already exists"));
4219
        goto cleanup;
C
Cole Robinson 已提交
4220 4221
    }

4222
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4223
        goto cleanup;
4224
    def = NULL;
C
Cole Robinson 已提交
4225

4226
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4227
        virStoragePoolObjRemove(&privconn->pools, pool);
4228 4229
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4230 4231 4232
    }
    pool->active = 1;

4233 4234
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4235

4236
 cleanup:
4237
    virStoragePoolDefFree(def);
4238 4239 4240
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4241
    return ret;
C
Cole Robinson 已提交
4242 4243 4244
}

static virStoragePoolPtr
4245 4246 4247
testStoragePoolDefineXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4248
{
4249
    testDriverPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4250
    virStoragePoolDefPtr def;
4251
    virStoragePoolObjPtr pool = NULL;
4252
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4253

E
Eric Blake 已提交
4254 4255
    virCheckFlags(0, NULL);

4256
    testDriverLock(privconn);
4257
    if (!(def = virStoragePoolDefParseString(xml)))
4258
        goto cleanup;
C
Cole Robinson 已提交
4259 4260 4261 4262 4263

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

4264
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4265 4266
        goto cleanup;
    def = NULL;
C
Cole Robinson 已提交
4267

4268
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4269
        virStoragePoolObjRemove(&privconn->pools, pool);
4270 4271
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4272 4273
    }

4274 4275
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4276

4277
 cleanup:
4278
    virStoragePoolDefFree(def);
4279 4280 4281
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4282
    return ret;
C
Cole Robinson 已提交
4283 4284 4285
}

static int
4286 4287
testStoragePoolUndefine(virStoragePoolPtr pool)
{
4288
    testDriverPtr privconn = pool->conn->privateData;
4289
    virStoragePoolObjPtr privpool;
4290
    int ret = -1;
4291

4292
    testDriverLock(privconn);
4293 4294 4295 4296
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
4297
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4298
        goto cleanup;
4299 4300
    }

4301
    if (virStoragePoolObjIsActive(privpool)) {
4302 4303
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4304 4305
        goto cleanup;
    }
C
Cole Robinson 已提交
4306 4307

    virStoragePoolObjRemove(&privconn->pools, privpool);
4308
    privpool = NULL;
4309
    ret = 0;
C
Cole Robinson 已提交
4310

4311
 cleanup:
4312 4313 4314
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
4315
    return ret;
C
Cole Robinson 已提交
4316 4317 4318
}

static int
4319
testStoragePoolBuild(virStoragePoolPtr pool,
E
Eric Blake 已提交
4320 4321
                     unsigned int flags)
{
4322
    testDriverPtr privconn = pool->conn->privateData;
4323
    virStoragePoolObjPtr privpool;
4324
    int ret = -1;
4325

E
Eric Blake 已提交
4326 4327
    virCheckFlags(0, -1);

4328
    testDriverLock(privconn);
4329 4330
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4331
    testDriverUnlock(privconn);
4332 4333

    if (privpool == NULL) {
4334
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4335
        goto cleanup;
4336 4337
    }

4338
    if (virStoragePoolObjIsActive(privpool)) {
4339 4340
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4341 4342
        goto cleanup;
    }
4343
    ret = 0;
C
Cole Robinson 已提交
4344

4345
 cleanup:
4346 4347
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4348
    return ret;
C
Cole Robinson 已提交
4349 4350 4351 4352
}


static int
4353 4354
testStoragePoolDestroy(virStoragePoolPtr pool)
{
4355
    testDriverPtr privconn = pool->conn->privateData;
4356
    virStoragePoolObjPtr privpool;
4357
    int ret = -1;
4358

4359
    testDriverLock(privconn);
4360 4361 4362 4363
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
4364
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4365
        goto cleanup;
4366 4367 4368
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4369 4370
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4371
        goto cleanup;
4372
    }
C
Cole Robinson 已提交
4373 4374 4375

    privpool->active = 0;

4376
    if (privpool->configFile == NULL) {
C
Cole Robinson 已提交
4377
        virStoragePoolObjRemove(&privconn->pools, privpool);
4378 4379
        privpool = NULL;
    }
4380
    ret = 0;
C
Cole Robinson 已提交
4381

4382
 cleanup:
4383 4384 4385
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
4386
    return ret;
C
Cole Robinson 已提交
4387 4388 4389 4390
}


static int
4391
testStoragePoolDelete(virStoragePoolPtr pool,
E
Eric Blake 已提交
4392 4393
                      unsigned int flags)
{
4394
    testDriverPtr privconn = pool->conn->privateData;
4395
    virStoragePoolObjPtr privpool;
4396
    int ret = -1;
4397

E
Eric Blake 已提交
4398 4399
    virCheckFlags(0, -1);

4400
    testDriverLock(privconn);
4401 4402
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4403
    testDriverUnlock(privconn);
4404 4405

    if (privpool == NULL) {
4406
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4407 4408 4409 4410
        goto cleanup;
    }

    if (virStoragePoolObjIsActive(privpool)) {
4411 4412
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4413
        goto cleanup;
4414 4415
    }

4416
    ret = 0;
C
Cole Robinson 已提交
4417

4418
 cleanup:
4419 4420
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4421
    return ret;
C
Cole Robinson 已提交
4422 4423 4424 4425
}


static int
4426
testStoragePoolRefresh(virStoragePoolPtr pool,
E
Eric Blake 已提交
4427 4428
                       unsigned int flags)
{
4429
    testDriverPtr privconn = pool->conn->privateData;
4430
    virStoragePoolObjPtr privpool;
4431
    int ret = -1;
4432

E
Eric Blake 已提交
4433 4434
    virCheckFlags(0, -1);

4435
    testDriverLock(privconn);
4436 4437
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4438
    testDriverUnlock(privconn);
4439 4440

    if (privpool == NULL) {
4441
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4442
        goto cleanup;
4443 4444 4445
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4446 4447
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4448
        goto cleanup;
4449
    }
4450
    ret = 0;
C
Cole Robinson 已提交
4451

4452
 cleanup:
4453 4454
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4455
    return ret;
C
Cole Robinson 已提交
4456 4457 4458 4459
}


static int
4460
testStoragePoolGetInfo(virStoragePoolPtr pool,
4461 4462
                       virStoragePoolInfoPtr info)
{
4463
    testDriverPtr privconn = pool->conn->privateData;
4464
    virStoragePoolObjPtr privpool;
4465
    int ret = -1;
4466

4467
    testDriverLock(privconn);
4468 4469
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4470
    testDriverUnlock(privconn);
4471 4472

    if (privpool == NULL) {
4473
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4474
        goto cleanup;
4475
    }
C
Cole Robinson 已提交
4476 4477 4478 4479 4480 4481 4482 4483 4484

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

4487
 cleanup:
4488 4489
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4490
    return ret;
C
Cole Robinson 已提交
4491 4492 4493
}

static char *
4494
testStoragePoolGetXMLDesc(virStoragePoolPtr pool,
E
Eric Blake 已提交
4495 4496
                          unsigned int flags)
{
4497
    testDriverPtr privconn = pool->conn->privateData;
4498
    virStoragePoolObjPtr privpool;
4499
    char *ret = NULL;
4500

E
Eric Blake 已提交
4501 4502
    virCheckFlags(0, NULL);

4503
    testDriverLock(privconn);
4504 4505
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4506
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4507

4508
    if (privpool == NULL) {
4509
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4510
        goto cleanup;
4511 4512
    }

4513
    ret = virStoragePoolDefFormat(privpool->def);
4514

4515
 cleanup:
4516 4517
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4518
    return ret;
C
Cole Robinson 已提交
4519 4520 4521
}

static int
4522
testStoragePoolGetAutostart(virStoragePoolPtr pool,
4523 4524
                            int *autostart)
{
4525
    testDriverPtr privconn = pool->conn->privateData;
4526
    virStoragePoolObjPtr privpool;
4527
    int ret = -1;
4528

4529
    testDriverLock(privconn);
4530 4531
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4532
    testDriverUnlock(privconn);
4533 4534

    if (privpool == NULL) {
4535
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4536
        goto cleanup;
4537
    }
C
Cole Robinson 已提交
4538 4539 4540 4541 4542 4543

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

4546
 cleanup:
4547 4548
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4549
    return ret;
C
Cole Robinson 已提交
4550 4551 4552
}

static int
4553
testStoragePoolSetAutostart(virStoragePoolPtr pool,
4554 4555
                            int autostart)
{
4556
    testDriverPtr privconn = pool->conn->privateData;
4557
    virStoragePoolObjPtr privpool;
4558
    int ret = -1;
4559

4560
    testDriverLock(privconn);
4561 4562
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4563
    testDriverUnlock(privconn);
4564 4565

    if (privpool == NULL) {
4566
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4567
        goto cleanup;
4568
    }
C
Cole Robinson 已提交
4569 4570

    if (!privpool->configFile) {
4571 4572
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("pool has no config file"));
4573
        goto cleanup;
C
Cole Robinson 已提交
4574 4575 4576 4577
    }

    autostart = (autostart != 0);
    privpool->autostart = autostart;
4578 4579
    ret = 0;

4580
 cleanup:
4581 4582
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4583
    return ret;
C
Cole Robinson 已提交
4584 4585 4586 4587
}


static int
4588 4589
testStoragePoolNumOfVolumes(virStoragePoolPtr pool)
{
4590
    testDriverPtr privconn = pool->conn->privateData;
4591
    virStoragePoolObjPtr privpool;
4592
    int ret = -1;
4593

4594
    testDriverLock(privconn);
4595 4596
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4597
    testDriverUnlock(privconn);
4598 4599

    if (privpool == NULL) {
4600
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4601
        goto cleanup;
4602 4603 4604
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4605 4606
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4607
        goto cleanup;
4608
    }
C
Cole Robinson 已提交
4609

4610 4611
    ret = privpool->volumes.count;

4612
 cleanup:
4613 4614
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4615
    return ret;
C
Cole Robinson 已提交
4616 4617 4618
}

static int
4619
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4620
                           char **const names,
4621 4622
                           int maxnames)
{
4623
    testDriverPtr privconn = pool->conn->privateData;
4624
    virStoragePoolObjPtr privpool;
4625 4626
    size_t i = 0;
    int n = 0;
C
Cole Robinson 已提交
4627

4628
    memset(names, 0, maxnames * sizeof(*names));
4629 4630

    testDriverLock(privconn);
4631 4632
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4633
    testDriverUnlock(privconn);
4634 4635

    if (privpool == NULL) {
4636
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4637
        goto cleanup;
4638 4639 4640 4641
    }


    if (!virStoragePoolObjIsActive(privpool)) {
4642 4643
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4644
        goto cleanup;
4645 4646
    }

4647
    for (i = 0; i < privpool->volumes.count && n < maxnames; i++) {
4648
        if (VIR_STRDUP(names[n++], privpool->volumes.objs[i]->name) < 0)
C
Cole Robinson 已提交
4649 4650 4651
            goto cleanup;
    }

4652
    virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4653 4654 4655
    return n;

 cleanup:
4656
    for (n = 0; n < maxnames; n++)
C
Cole Robinson 已提交
4657 4658
        VIR_FREE(names[i]);

4659
    memset(names, 0, maxnames * sizeof(*names));
4660 4661
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4662 4663 4664
    return -1;
}

4665 4666 4667
static int
testStoragePoolListAllVolumes(virStoragePoolPtr obj,
                              virStorageVolPtr **vols,
4668 4669
                              unsigned int flags)
{
4670
    testDriverPtr privconn = obj->conn->privateData;
4671
    virStoragePoolObjPtr pool;
4672
    size_t i;
4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701
    virStorageVolPtr *tmp_vols = NULL;
    virStorageVolPtr vol = NULL;
    int nvols = 0;
    int ret = -1;

    virCheckFlags(0, -1);

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

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

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

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

4702
    if (VIR_ALLOC_N(tmp_vols, pool->volumes.count + 1) < 0)
4703 4704
         goto cleanup;

4705
    for (i = 0; i < pool->volumes.count; i++) {
4706 4707
        if (!(vol = virGetStorageVol(obj->conn, pool->def->name,
                                     pool->volumes.objs[i]->name,
4708 4709
                                     pool->volumes.objs[i]->key,
                                     NULL, NULL)))
4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723
            goto cleanup;
        tmp_vols[nvols++] = vol;
    }

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

 cleanup:
    if (tmp_vols) {
        for (i = 0; i < nvols; i++) {
            if (tmp_vols[i])
                virStorageVolFree(tmp_vols[i]);
        }
4724
        VIR_FREE(tmp_vols);
4725 4726 4727 4728 4729 4730 4731
    }

    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
C
Cole Robinson 已提交
4732 4733

static virStorageVolPtr
4734
testStorageVolLookupByName(virStoragePoolPtr pool,
4735 4736
                           const char *name ATTRIBUTE_UNUSED)
{
4737
    testDriverPtr privconn = pool->conn->privateData;
4738 4739
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
4740
    virStorageVolPtr ret = NULL;
4741

4742
    testDriverLock(privconn);
4743 4744
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4745
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4746

4747
    if (privpool == NULL) {
4748
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4749
        goto cleanup;
4750 4751 4752 4753
    }


    if (!virStoragePoolObjIsActive(privpool)) {
4754 4755
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4756
        goto cleanup;
4757 4758 4759 4760 4761
    }

    privvol = virStorageVolDefFindByName(privpool, name);

    if (!privvol) {
4762 4763
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"), name);
4764
        goto cleanup;
C
Cole Robinson 已提交
4765 4766
    }

4767
    ret = virGetStorageVol(pool->conn, privpool->def->name,
4768 4769
                           privvol->name, privvol->key,
                           NULL, NULL);
4770

4771
 cleanup:
4772 4773
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4774
    return ret;
C
Cole Robinson 已提交
4775 4776 4777 4778
}


static virStorageVolPtr
4779
testStorageVolLookupByKey(virConnectPtr conn,
4780 4781
                          const char *key)
{
4782
    testDriverPtr privconn = conn->privateData;
4783
    size_t i;
4784
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4785

4786
    testDriverLock(privconn);
4787
    for (i = 0; i < privconn->pools.count; i++) {
4788
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4789
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4790
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4791 4792
                virStorageVolDefFindByKey(privconn->pools.objs[i], key);

4793 4794 4795 4796
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
4797 4798
                                       privvol->key,
                                       NULL, NULL);
4799
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
4800 4801
                break;
            }
C
Cole Robinson 已提交
4802
        }
4803
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4804
    }
4805
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4806

4807
    if (!ret)
4808 4809
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching key '%s'"), key);
4810 4811

    return ret;
C
Cole Robinson 已提交
4812 4813 4814
}

static virStorageVolPtr
4815
testStorageVolLookupByPath(virConnectPtr conn,
4816 4817
                           const char *path)
{
4818
    testDriverPtr privconn = conn->privateData;
4819
    size_t i;
4820
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4821

4822
    testDriverLock(privconn);
4823
    for (i = 0; i < privconn->pools.count; i++) {
4824
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4825
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4826
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4827 4828
                virStorageVolDefFindByPath(privconn->pools.objs[i], path);

4829 4830 4831 4832
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
4833 4834
                                       privvol->key,
                                       NULL, NULL);
4835
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
4836 4837
                break;
            }
C
Cole Robinson 已提交
4838
        }
4839
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4840
    }
4841
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4842

4843
    if (!ret)
4844 4845
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching path '%s'"), path);
4846 4847

    return ret;
C
Cole Robinson 已提交
4848 4849 4850
}

static virStorageVolPtr
4851 4852 4853
testStorageVolCreateXML(virStoragePoolPtr pool,
                        const char *xmldesc,
                        unsigned int flags)
E
Eric Blake 已提交
4854
{
4855
    testDriverPtr privconn = pool->conn->privateData;
4856
    virStoragePoolObjPtr privpool;
4857 4858
    virStorageVolDefPtr privvol = NULL;
    virStorageVolPtr ret = NULL;
4859

E
Eric Blake 已提交
4860 4861
    virCheckFlags(0, NULL);

4862
    testDriverLock(privconn);
4863 4864
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4865
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4866

4867
    if (privpool == NULL) {
4868
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4869
        goto cleanup;
4870 4871 4872
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4873 4874
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4875
        goto cleanup;
4876
    }
C
Cole Robinson 已提交
4877

4878
    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
4879
    if (privvol == NULL)
4880
        goto cleanup;
4881 4882

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
4883 4884
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
4885
        goto cleanup;
C
Cole Robinson 已提交
4886 4887 4888
    }

    /* Make sure enough space */
4889
    if ((privpool->def->allocation + privvol->target.allocation) >
C
Cole Robinson 已提交
4890
         privpool->def->capacity) {
4891 4892 4893
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
4894
        goto cleanup;
C
Cole Robinson 已提交
4895 4896
    }

4897 4898
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
4899
                    privvol->name) == -1)
4900
        goto cleanup;
C
Cole Robinson 已提交
4901

4902 4903 4904
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
        VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
                                privpool->volumes.count, privvol) < 0)
4905
        goto cleanup;
C
Cole Robinson 已提交
4906

4907
    privpool->def->allocation += privvol->target.allocation;
C
Cole Robinson 已提交
4908 4909 4910
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

4911
    ret = virGetStorageVol(pool->conn, privpool->def->name,
4912 4913
                           privvol->name, privvol->key,
                           NULL, NULL);
4914
    privvol = NULL;
4915

4916
 cleanup:
4917
    virStorageVolDefFree(privvol);
4918 4919
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4920
    return ret;
C
Cole Robinson 已提交
4921 4922
}

4923
static virStorageVolPtr
4924 4925 4926 4927
testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
                            const char *xmldesc,
                            virStorageVolPtr clonevol,
                            unsigned int flags)
E
Eric Blake 已提交
4928
{
4929
    testDriverPtr privconn = pool->conn->privateData;
4930 4931 4932 4933
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol = NULL, origvol = NULL;
    virStorageVolPtr ret = NULL;

E
Eric Blake 已提交
4934 4935
    virCheckFlags(0, NULL);

4936 4937 4938 4939 4940 4941
    testDriverLock(privconn);
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
    testDriverUnlock(privconn);

    if (privpool == NULL) {
4942
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4943 4944 4945 4946
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4947 4948
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4949 4950 4951
        goto cleanup;
    }

4952
    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
4953 4954 4955 4956
    if (privvol == NULL)
        goto cleanup;

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
4957 4958
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
4959 4960 4961 4962 4963
        goto cleanup;
    }

    origvol = virStorageVolDefFindByName(privpool, clonevol->name);
    if (!origvol) {
4964 4965 4966
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       clonevol->name);
4967 4968 4969 4970
        goto cleanup;
    }

    /* Make sure enough space */
4971
    if ((privpool->def->allocation + privvol->target.allocation) >
4972
         privpool->def->capacity) {
4973 4974 4975
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
4976 4977 4978 4979 4980
        goto cleanup;
    }
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

4981 4982
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
4983
                    privvol->name) == -1)
4984 4985
        goto cleanup;

4986 4987 4988
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
        VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
                                privpool->volumes.count, privvol) < 0)
4989 4990
        goto cleanup;

4991
    privpool->def->allocation += privvol->target.allocation;
4992 4993 4994 4995
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    ret = virGetStorageVol(pool->conn, privpool->def->name,
4996 4997
                           privvol->name, privvol->key,
                           NULL, NULL);
4998 4999
    privvol = NULL;

5000
 cleanup:
5001 5002 5003 5004 5005 5006
    virStorageVolDefFree(privvol);
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    return ret;
}

C
Cole Robinson 已提交
5007
static int
5008 5009
testStorageVolDelete(virStorageVolPtr vol,
                     unsigned int flags)
E
Eric Blake 已提交
5010
{
5011
    testDriverPtr privconn = vol->conn->privateData;
5012 5013
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5014
    size_t i;
5015
    int ret = -1;
C
Cole Robinson 已提交
5016

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

5019
    testDriverLock(privconn);
5020 5021
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5022
    testDriverUnlock(privconn);
5023 5024

    if (privpool == NULL) {
5025
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5026
        goto cleanup;
5027 5028 5029 5030 5031 5032
    }


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

    if (privvol == NULL) {
5033 5034 5035
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5036
        goto cleanup;
5037 5038 5039
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5040 5041
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5042
        goto cleanup;
5043 5044 5045
    }


5046
    privpool->def->allocation -= privvol->target.allocation;
C
Cole Robinson 已提交
5047 5048 5049
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

5050
    for (i = 0; i < privpool->volumes.count; i++) {
C
Cole Robinson 已提交
5051 5052 5053
        if (privpool->volumes.objs[i] == privvol) {
            virStorageVolDefFree(privvol);

5054
            VIR_DELETE_ELEMENT(privpool->volumes.objs, i, privpool->volumes.count);
C
Cole Robinson 已提交
5055 5056 5057
            break;
        }
    }
5058
    ret = 0;
C
Cole Robinson 已提交
5059

5060
 cleanup:
5061 5062
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5063
    return ret;
C
Cole Robinson 已提交
5064 5065 5066
}


5067 5068
static int testStorageVolumeTypeForPool(int pooltype)
{
C
Cole Robinson 已提交
5069

5070
    switch (pooltype) {
C
Cole Robinson 已提交
5071 5072 5073 5074 5075 5076 5077 5078 5079 5080
        case VIR_STORAGE_POOL_DIR:
        case VIR_STORAGE_POOL_FS:
        case VIR_STORAGE_POOL_NETFS:
            return VIR_STORAGE_VOL_FILE;
        default:
            return VIR_STORAGE_VOL_BLOCK;
    }
}

static int
5081
testStorageVolGetInfo(virStorageVolPtr vol,
5082 5083
                      virStorageVolInfoPtr info)
{
5084
    testDriverPtr privconn = vol->conn->privateData;
5085 5086
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5087
    int ret = -1;
5088

5089
    testDriverLock(privconn);
5090 5091
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5092
    testDriverUnlock(privconn);
5093 5094

    if (privpool == NULL) {
5095
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5096
        goto cleanup;
5097 5098 5099 5100 5101
    }

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

    if (privvol == NULL) {
5102 5103 5104
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5105
        goto cleanup;
5106 5107 5108
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5109 5110
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5111
        goto cleanup;
5112
    }
C
Cole Robinson 已提交
5113 5114 5115

    memset(info, 0, sizeof(*info));
    info->type = testStorageVolumeTypeForPool(privpool->def->type);
5116 5117
    info->capacity = privvol->target.capacity;
    info->allocation = privvol->target.allocation;
5118
    ret = 0;
C
Cole Robinson 已提交
5119

5120
 cleanup:
5121 5122
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5123
    return ret;
C
Cole Robinson 已提交
5124 5125 5126
}

static char *
5127 5128
testStorageVolGetXMLDesc(virStorageVolPtr vol,
                         unsigned int flags)
E
Eric Blake 已提交
5129
{
5130
    testDriverPtr privconn = vol->conn->privateData;
5131 5132
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5133
    char *ret = NULL;
5134

E
Eric Blake 已提交
5135 5136
    virCheckFlags(0, NULL);

5137
    testDriverLock(privconn);
5138 5139
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5140
    testDriverUnlock(privconn);
5141 5142

    if (privpool == NULL) {
5143
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5144
        goto cleanup;
5145 5146 5147 5148 5149
    }

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

    if (privvol == NULL) {
5150 5151 5152
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5153
        goto cleanup;
5154
    }
C
Cole Robinson 已提交
5155

5156
    if (!virStoragePoolObjIsActive(privpool)) {
5157 5158
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5159
        goto cleanup;
5160 5161
    }

5162
    ret = virStorageVolDefFormat(privpool->def, privvol);
5163

5164
 cleanup:
5165 5166
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5167
    return ret;
C
Cole Robinson 已提交
5168 5169 5170
}

static char *
5171 5172
testStorageVolGetPath(virStorageVolPtr vol)
{
5173
    testDriverPtr privconn = vol->conn->privateData;
5174 5175
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5176
    char *ret = NULL;
5177

5178
    testDriverLock(privconn);
5179 5180
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5181
    testDriverUnlock(privconn);
5182 5183

    if (privpool == NULL) {
5184
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5185
        goto cleanup;
5186 5187 5188 5189 5190
    }

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

    if (privvol == NULL) {
5191 5192 5193
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5194
        goto cleanup;
5195 5196 5197
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5198 5199
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5200
        goto cleanup;
5201 5202
    }

5203
    ignore_value(VIR_STRDUP(ret, privvol->target.path));
5204

5205
 cleanup:
5206 5207
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
5208 5209 5210
    return ret;
}

5211

5212
/* Node device implementations */
5213

5214 5215 5216
static int
testNodeNumOfDevices(virConnectPtr conn,
                     const char *cap,
E
Eric Blake 已提交
5217
                     unsigned int flags)
5218
{
5219
    testDriverPtr driver = conn->privateData;
5220
    int ndevs = 0;
5221
    size_t i;
5222

E
Eric Blake 已提交
5223 5224
    virCheckFlags(0, -1);

5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239
    testDriverLock(driver);
    for (i = 0; i < driver->devs.count; i++)
        if ((cap == NULL) ||
            virNodeDeviceHasCap(driver->devs.objs[i], cap))
            ++ndevs;
    testDriverUnlock(driver);

    return ndevs;
}

static int
testNodeListDevices(virConnectPtr conn,
                    const char *cap,
                    char **const names,
                    int maxnames,
E
Eric Blake 已提交
5240
                    unsigned int flags)
5241
{
5242
    testDriverPtr driver = conn->privateData;
5243
    int ndevs = 0;
5244
    size_t i;
5245

E
Eric Blake 已提交
5246 5247
    virCheckFlags(0, -1);

5248 5249 5250 5251 5252
    testDriverLock(driver);
    for (i = 0; i < driver->devs.count && ndevs < maxnames; i++) {
        virNodeDeviceObjLock(driver->devs.objs[i]);
        if (cap == NULL ||
            virNodeDeviceHasCap(driver->devs.objs[i], cap)) {
5253
            if (VIR_STRDUP(names[ndevs++], driver->devs.objs[i]->def->name) < 0) {
5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274
                virNodeDeviceObjUnlock(driver->devs.objs[i]);
                goto failure;
            }
        }
        virNodeDeviceObjUnlock(driver->devs.objs[i]);
    }
    testDriverUnlock(driver);

    return ndevs;

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

static virNodeDevicePtr
testNodeDeviceLookupByName(virConnectPtr conn, const char *name)
{
5275
    testDriverPtr driver = conn->privateData;
5276 5277 5278 5279 5280 5281 5282 5283
    virNodeDeviceObjPtr obj;
    virNodeDevicePtr ret = NULL;

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

    if (!obj) {
5284 5285 5286
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       name);
5287 5288 5289 5290 5291
        goto cleanup;
    }

    ret = virGetNodeDevice(conn, name);

5292
 cleanup:
5293 5294 5295 5296 5297 5298
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

static char *
5299
testNodeDeviceGetXMLDesc(virNodeDevicePtr dev,
E
Eric Blake 已提交
5300
                         unsigned int flags)
5301
{
5302
    testDriverPtr driver = dev->conn->privateData;
5303 5304 5305
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

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

5308 5309 5310 5311 5312
    testDriverLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
    testDriverUnlock(driver);

    if (!obj) {
5313 5314 5315
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5316 5317 5318
        goto cleanup;
    }

5319
    ret = virNodeDeviceDefFormat(obj->def);
5320

5321
 cleanup:
5322 5323 5324 5325 5326 5327 5328 5329
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

static char *
testNodeDeviceGetParent(virNodeDevicePtr dev)
{
5330
    testDriverPtr driver = dev->conn->privateData;
5331 5332 5333 5334 5335 5336 5337 5338
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

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

    if (!obj) {
5339 5340 5341
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5342 5343 5344 5345
        goto cleanup;
    }

    if (obj->def->parent) {
5346
        ignore_value(VIR_STRDUP(ret, obj->def->parent));
5347
    } else {
5348 5349
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no parent for this device"));
5350 5351
    }

5352
 cleanup:
5353 5354 5355 5356 5357
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

5358

5359 5360 5361
static int
testNodeDeviceNumOfCaps(virNodeDevicePtr dev)
{
5362
    testDriverPtr driver = dev->conn->privateData;
5363 5364 5365 5366 5367 5368 5369 5370 5371 5372
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

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

    if (!obj) {
5373 5374 5375
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5376 5377 5378 5379 5380 5381 5382
        goto cleanup;
    }

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

5383
 cleanup:
5384 5385 5386 5387 5388 5389 5390 5391 5392
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}


static int
testNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
5393
    testDriverPtr driver = dev->conn->privateData;
5394 5395 5396 5397 5398 5399 5400 5401 5402 5403
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

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

    if (!obj) {
5404 5405 5406
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5407 5408 5409 5410
        goto cleanup;
    }

    for (caps = obj->def->caps; caps && ncaps < maxnames; caps = caps->next) {
5411
        if (VIR_STRDUP(names[ncaps++], virNodeDevCapTypeToString(caps->data.type)) < 0)
5412 5413 5414 5415
            goto cleanup;
    }
    ret = ncaps;

5416
 cleanup:
5417 5418 5419 5420 5421 5422 5423 5424 5425 5426
    if (obj)
        virNodeDeviceObjUnlock(obj);
    if (ret == -1) {
        --ncaps;
        while (--ncaps >= 0)
            VIR_FREE(names[ncaps]);
    }
    return ret;
}

5427 5428 5429
static virNodeDevicePtr
testNodeDeviceCreateXML(virConnectPtr conn,
                        const char *xmlDesc,
E
Eric Blake 已提交
5430
                        unsigned int flags)
5431
{
5432
    testDriverPtr driver = conn->privateData;
5433 5434 5435 5436 5437 5438 5439
    virNodeDeviceDefPtr def = NULL;
    virNodeDeviceObjPtr obj = NULL;
    char *wwnn = NULL, *wwpn = NULL;
    int parent_host = -1;
    virNodeDevicePtr dev = NULL;
    virNodeDevCapsDefPtr caps;

E
Eric Blake 已提交
5440 5441
    virCheckFlags(0, NULL);

5442 5443
    testDriverLock(driver);

5444
    def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, NULL);
5445
    if (def == NULL)
5446 5447 5448
        goto cleanup;

    /* We run these next two simply for validation */
5449
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) == -1)
5450 5451
        goto cleanup;

5452
    if (virNodeDeviceGetParentHost(&driver->devs,
5453 5454 5455 5456 5457 5458 5459 5460 5461
                                   def->name,
                                   def->parent,
                                   &parent_host) == -1) {
        goto cleanup;
    }

    /* 'name' is supposed to be filled in by the node device backend, which
     * we don't have. Use WWPN instead. */
    VIR_FREE(def->name);
5462
    if (VIR_STRDUP(def->name, wwpn) < 0)
5463 5464
        goto cleanup;

J
John Ferlan 已提交
5465 5466
    /* Fill in a random 'host' and 'unique_id' value,
     * since this would also come from the backend */
5467 5468
    caps = def->caps;
    while (caps) {
5469
        if (caps->data.type != VIR_NODE_DEV_CAP_SCSI_HOST)
5470 5471
            continue;

5472
        caps->data.scsi_host.host = virRandomBits(10);
J
John Ferlan 已提交
5473
        caps->data.scsi_host.unique_id = 2;
5474 5475 5476 5477
        caps = caps->next;
    }


5478
    if (!(obj = virNodeDeviceAssignDef(&driver->devs, def)))
5479 5480 5481 5482 5483
        goto cleanup;
    virNodeDeviceObjUnlock(obj);

    dev = virGetNodeDevice(conn, def->name);
    def = NULL;
5484
 cleanup:
5485
    testDriverUnlock(driver);
5486
    virNodeDeviceDefFree(def);
5487 5488 5489 5490 5491 5492 5493 5494 5495
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return dev;
}

static int
testNodeDeviceDestroy(virNodeDevicePtr dev)
{
    int ret = 0;
5496
    testDriverPtr driver = dev->conn->privateData;
5497 5498 5499 5500 5501 5502 5503 5504 5505
    virNodeDeviceObjPtr obj = NULL;
    char *parent_name = NULL, *wwnn = NULL, *wwpn = NULL;
    int parent_host = -1;

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

    if (!obj) {
5506 5507 5508
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5509 5510 5511
        goto out;
    }

5512
    if (virNodeDeviceGetWWNs(obj->def, &wwnn, &wwpn) == -1)
5513 5514
        goto out;

5515
    if (VIR_STRDUP(parent_name, obj->def->parent) < 0)
5516 5517 5518 5519 5520 5521 5522 5523 5524
        goto out;

    /* virNodeDeviceGetParentHost will cause the device object's lock to be
     * taken, so we have to dup the parent's name and drop the lock
     * before calling it.  We don't need the reference to the object
     * any more once we have the parent's name.  */
    virNodeDeviceObjUnlock(obj);

    /* We do this just for basic validation */
5525
    if (virNodeDeviceGetParentHost(&driver->devs,
5526 5527 5528 5529 5530 5531 5532 5533 5534 5535
                                   dev->name,
                                   parent_name,
                                   &parent_host) == -1) {
        obj = NULL;
        goto out;
    }

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

5536
 out:
5537 5538 5539 5540 5541 5542 5543 5544
    if (obj)
        virNodeDeviceObjUnlock(obj);
    VIR_FREE(parent_name);
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return ret;
}

5545 5546

/* Domain event implementations */
5547
static int
5548 5549 5550 5551
testConnectDomainEventRegister(virConnectPtr conn,
                               virConnectDomainEventCallback callback,
                               void *opaque,
                               virFreeCallback freecb)
5552
{
5553
    testDriverPtr driver = conn->privateData;
5554
    int ret = 0;
5555

5556
    if (virDomainEventStateRegister(conn, driver->eventState,
5557 5558
                                    callback, opaque, freecb) < 0)
        ret = -1;
5559 5560 5561 5562

    return ret;
}

5563

5564
static int
5565 5566
testConnectDomainEventDeregister(virConnectPtr conn,
                                 virConnectDomainEventCallback callback)
5567
{
5568
    testDriverPtr driver = conn->privateData;
5569
    int ret = 0;
5570

5571
    if (virDomainEventStateDeregister(conn, driver->eventState,
5572 5573
                                      callback) < 0)
        ret = -1;
5574 5575 5576 5577

    return ret;
}

5578 5579

static int
5580 5581 5582 5583 5584 5585
testConnectDomainEventRegisterAny(virConnectPtr conn,
                                  virDomainPtr dom,
                                  int eventID,
                                  virConnectDomainEventGenericCallback callback,
                                  void *opaque,
                                  virFreeCallback freecb)
5586
{
5587
    testDriverPtr driver = conn->privateData;
5588 5589
    int ret;

5590
    if (virDomainEventStateRegisterID(conn, driver->eventState,
5591 5592
                                      dom, eventID,
                                      callback, opaque, freecb, &ret) < 0)
5593
        ret = -1;
5594 5595 5596 5597 5598

    return ret;
}

static int
5599 5600
testConnectDomainEventDeregisterAny(virConnectPtr conn,
                                    int callbackID)
5601
{
5602
    testDriverPtr driver = conn->privateData;
5603
    int ret = 0;
5604

5605
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5606 5607
                                        callbackID) < 0)
        ret = -1;
5608 5609 5610 5611 5612

    return ret;
}


5613 5614 5615 5616 5617 5618 5619 5620
static int
testConnectNetworkEventRegisterAny(virConnectPtr conn,
                                   virNetworkPtr net,
                                   int eventID,
                                   virConnectNetworkEventGenericCallback callback,
                                   void *opaque,
                                   virFreeCallback freecb)
{
5621
    testDriverPtr driver = conn->privateData;
5622 5623
    int ret;

5624
    if (virNetworkEventStateRegisterID(conn, driver->eventState,
5625
                                       net, eventID, callback,
5626 5627 5628 5629 5630 5631 5632 5633 5634 5635
                                       opaque, freecb, &ret) < 0)
        ret = -1;

    return ret;
}

static int
testConnectNetworkEventDeregisterAny(virConnectPtr conn,
                                     int callbackID)
{
5636
    testDriverPtr driver = conn->privateData;
5637
    int ret = 0;
5638

5639
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5640 5641
                                        callbackID) < 0)
        ret = -1;
5642 5643 5644 5645

    return ret;
}

5646 5647 5648
static int testConnectListAllDomains(virConnectPtr conn,
                                     virDomainPtr **domains,
                                     unsigned int flags)
5649
{
5650
    testDriverPtr privconn = conn->privateData;
5651

O
Osier Yang 已提交
5652
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
5653

5654 5655
    return virDomainObjListExport(privconn->domains, conn, domains,
                                  NULL, flags);
5656 5657
}

5658
static int
P
Peter Krempa 已提交
5659
testNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,
5660 5661 5662 5663 5664 5665 5666
                  unsigned char **cpumap,
                  unsigned int *online,
                  unsigned int flags)
{
    virCheckFlags(0, -1);

    if (cpumap) {
5667
        if (VIR_ALLOC_N(*cpumap, 1) < 0)
P
Peter Krempa 已提交
5668
            return -1;
5669 5670 5671 5672 5673 5674
        *cpumap[0] = 0x15;
    }

    if (online)
        *online = 3;

P
Peter Krempa 已提交
5675
    return  8;
5676 5677
}

5678 5679 5680 5681 5682 5683 5684 5685 5686 5687
static char *
testDomainScreenshot(virDomainPtr dom ATTRIBUTE_UNUSED,
                     virStreamPtr st,
                     unsigned int screen ATTRIBUTE_UNUSED,
                     unsigned int flags)
{
    char *ret = NULL;

    virCheckFlags(0, NULL);

5688
    if (VIR_STRDUP(ret, "image/png") < 0)
5689 5690
        return NULL;

5691
    if (virFDStreamOpenFile(st, PKGDATADIR "/libvirtLogo.png", 0, 0, O_RDONLY) < 0)
5692 5693 5694 5695 5696
        VIR_FREE(ret);

    return ret;
}

5697 5698 5699 5700 5701 5702 5703 5704 5705
static int
testConnectGetCPUModelNames(virConnectPtr conn ATTRIBUTE_UNUSED,
                            const char *arch,
                            char ***models,
                            unsigned int flags)
{
    virCheckFlags(0, -1);
    return cpuGetModels(arch, models);
}
5706

C
Cole Robinson 已提交
5707 5708 5709
static int
testDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
5710
    testDriverPtr privconn = dom->conn->privateData;
C
Cole Robinson 已提交
5711
    virDomainObjPtr vm = NULL;
5712
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
5713 5714 5715 5716 5717 5718
    int ret = -1;

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

5719 5720
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734

    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);
5735
    event = virDomainEventLifecycleNewFromObj(vm,
C
Cole Robinson 已提交
5736 5737 5738 5739 5740
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
    vm->hasManagedSave = true;

    ret = 0;
5741
 cleanup:
5742
    virDomainObjEndAPI(&vm);
5743
    testObjectEventQueue(privconn, event);
C
Cole Robinson 已提交
5744 5745 5746 5747 5748 5749 5750 5751 5752

    return ret;
}


static int
testDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm;
5753
    int ret;
C
Cole Robinson 已提交
5754 5755 5756

    virCheckFlags(0, -1);

5757 5758
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5759 5760

    ret = vm->hasManagedSave;
5761

5762
    virDomainObjEndAPI(&vm);
C
Cole Robinson 已提交
5763 5764 5765 5766 5767 5768 5769 5770 5771 5772
    return ret;
}

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

    virCheckFlags(0, -1);

5773 5774
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5775 5776

    vm->hasManagedSave = false;
5777

5778
    virDomainObjEndAPI(&vm);
5779
    return 0;
C
Cole Robinson 已提交
5780 5781 5782
}


5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816
/*
 * 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;
5817
    int n;
5818 5819 5820 5821 5822

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5823
        return -1;
5824 5825 5826

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

5827
    virDomainObjEndAPI(&vm);
5828 5829 5830 5831 5832 5833 5834 5835 5836 5837
    return n;
}

static int
testDomainSnapshotListNames(virDomainPtr domain,
                            char **names,
                            int nameslen,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
5838
    int n;
5839 5840 5841 5842 5843

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5844
        return -1;
5845 5846 5847 5848

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

5849
    virDomainObjEndAPI(&vm);
5850 5851 5852 5853 5854 5855 5856 5857 5858
    return n;
}

static int
testDomainListAllSnapshots(virDomainPtr domain,
                           virDomainSnapshotPtr **snaps,
                           unsigned int flags)
{
    virDomainObjPtr vm = NULL;
5859
    int n;
5860 5861 5862 5863 5864

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5865
        return -1;
5866 5867 5868

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

5869
    virDomainObjEndAPI(&vm);
5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886
    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)))
5887
        return -1;
5888 5889 5890 5891 5892 5893 5894

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

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

5895
 cleanup:
5896
    virDomainObjEndAPI(&vm);
5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911
    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)))
5912
        return -1;
5913 5914 5915 5916 5917 5918

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

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

5919
 cleanup:
5920
    virDomainObjEndAPI(&vm);
5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936
    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)))
5937
        return -1;
5938 5939 5940 5941 5942 5943 5944

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

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

5945
 cleanup:
5946
    virDomainObjEndAPI(&vm);
5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961
    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)))
5962
        return NULL;
5963 5964 5965 5966 5967 5968

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

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

5969
 cleanup:
5970
    virDomainObjEndAPI(&vm);
5971 5972 5973 5974 5975 5976 5977 5978
    return snapshot;
}

static int
testDomainHasCurrentSnapshot(virDomainPtr domain,
                             unsigned int flags)
{
    virDomainObjPtr vm;
5979
    int ret;
5980 5981 5982 5983

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5984
        return -1;
5985 5986 5987

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

5988
    virDomainObjEndAPI(&vm);
5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002
    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)))
6003
        return NULL;
6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016

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

6017
 cleanup:
6018
    virDomainObjEndAPI(&vm);
6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031
    return parent;
}

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

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
6032
        return NULL;
6033 6034 6035 6036 6037 6038 6039 6040 6041

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

6042
 cleanup:
6043
    virDomainObjEndAPI(&vm);
6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054
    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];
6055
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6056 6057 6058 6059

    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6060
        return NULL;
6061 6062 6063 6064 6065 6066

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

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

6067
    xml = virDomainSnapshotDefFormat(uuidstr, snap->def, privconn->caps,
6068 6069
                                     virDomainDefFormatConvertXMLFlags(flags),
                                     0);
6070

6071
 cleanup:
6072
    virDomainObjEndAPI(&vm);
6073 6074 6075 6076 6077 6078 6079 6080
    return xml;
}

static int
testDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6081
    int ret;
6082 6083 6084 6085

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6086
        return -1;
6087 6088 6089 6090

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

6091
    virDomainObjEndAPI(&vm);
6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105
    return ret;
}


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

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6106
        return -1;
6107

C
Cole Robinson 已提交
6108
    if (!testSnapObjFromSnapshot(vm, snapshot))
6109 6110 6111 6112
        goto cleanup;

    ret = 1;

6113
 cleanup:
6114
    virDomainObjEndAPI(&vm);
6115 6116 6117
    return ret;
}

6118 6119 6120 6121 6122 6123
static int
testDomainSnapshotAlignDisks(virDomainObjPtr vm,
                             virDomainSnapshotDefPtr def,
                             unsigned int flags)
{
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
E
Eric Blake 已提交
6124
    bool align_match = true;
6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152

    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)
{
6153
    testDriverPtr privconn = domain->conn->privateData;
6154 6155 6156 6157
    virDomainObjPtr vm = NULL;
    virDomainSnapshotDefPtr def = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr snapshot = NULL;
6158
    virObjectEventPtr event = NULL;
6159
    char *xml = NULL;
6160 6161
    bool update_current = true;
    bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
6162 6163 6164 6165 6166 6167 6168 6169
    unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;

    /*
     * DISK_ONLY: Not implemented yet
     * REUSE_EXT: Not implemented yet
     *
     * NO_METADATA: Explicitly not implemented
     *
6170
     * REDEFINE + CURRENT: Implemented
6171 6172 6173 6174 6175 6176
     * HALT: Implemented
     * QUIESCE: Nothing to do
     * ATOMIC: Nothing to do
     * LIVE: Nothing to do
     */
    virCheckFlags(
6177 6178
        VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
        VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
6179 6180 6181 6182 6183
        VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
        VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
        VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
        VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, NULL);

6184 6185 6186 6187 6188
    if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)))
        update_current = false;
    if (redefine)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;

6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203
    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;

6204
    if (redefine) {
C
Cole Robinson 已提交
6205 6206
        if (virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
                                          &update_current, flags) < 0)
6207 6208 6209 6210 6211 6212 6213
            goto cleanup;
    } else {
        if (!(def->dom = virDomainDefCopy(vm->def,
                                          privconn->caps,
                                          privconn->xmlopt,
                                          true)))
            goto cleanup;
6214

6215
        if (testDomainSnapshotAlignDisks(vm, def, flags) < 0)
6216 6217 6218
            goto cleanup;
    }

6219 6220 6221 6222
    if (!snap) {
        if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
            goto cleanup;
        def = NULL;
6223 6224
    }

6225 6226 6227 6228 6229 6230 6231 6232 6233 6234
    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);
6235
            event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
6236 6237 6238
                                    VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
        }
    }
6239 6240

    snapshot = virGetDomainSnapshot(domain, snap->def->name);
6241
 cleanup:
6242 6243 6244 6245
    VIR_FREE(xml);
    if (vm) {
        if (snapshot) {
            virDomainSnapshotObjPtr other;
6246 6247
            if (update_current)
                vm->current_snapshot = snap;
6248 6249 6250 6251 6252 6253 6254
            other = virDomainSnapshotFindByName(vm->snapshots,
                                                snap->def->parent);
            snap->parent = other;
            other->nchildren++;
            snap->sibling = other->first_child;
            other->first_child = snap;
        }
6255
        virDomainObjEndAPI(&vm);
6256
    }
6257
    testObjectEventQueue(privconn, event);
6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269
    virDomainSnapshotDefFree(def);
    return snapshot;
}


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

6270
static int
6271
testDomainSnapshotDiscardAll(void *payload,
6272 6273
                             const void *name ATTRIBUTE_UNUSED,
                             void *data)
6274 6275 6276 6277 6278 6279 6280
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapRemoveDataPtr curr = data;

    if (snap->def->current)
        curr->current = true;
    virDomainSnapshotObjListRemove(curr->vm->snapshots, snap);
6281
    return 0;
6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292
}

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

6293
static int
6294 6295 6296 6297 6298 6299 6300
testDomainSnapshotReparentChildren(void *payload,
                                   const void *name ATTRIBUTE_UNUSED,
                                   void *data)
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapReparentDataPtr rep = data;

6301
    if (rep->err < 0)
6302
        return 0;
6303 6304 6305 6306 6307 6308 6309

    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;
6310
        return 0;
6311 6312 6313 6314
    }

    if (!snap->sibling)
        rep->last = snap;
6315
    return 0;
6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344
}

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) {
6345
            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)
6346 6347 6348 6349 6350 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 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388
                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;
6389
 cleanup:
6390
    virDomainObjEndAPI(&vm);
6391 6392 6393 6394 6395 6396 6397
    return ret;
}

static int
testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                           unsigned int flags)
{
6398
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6399 6400
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
6401 6402
    virObjectEventPtr event = NULL;
    virObjectEventPtr event2 = NULL;
6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493
    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;
    config = virDomainDefCopy(snap->def->dom,
                              privconn->caps, privconn->xmlopt, true);
    if (!config)
        goto cleanup;

    if (snap->def->state == VIR_DOMAIN_RUNNING ||
        snap->def->state == VIR_DOMAIN_PAUSED) {
        /* Transitions 2, 3, 5, 6, 8, 9 */
        bool was_running = false;
        bool was_stopped = false;

        if (virDomainObjIsActive(vm)) {
            /* Transitions 5, 6, 8, 9 */
            /* Check for ABI compatibility.  */
            if (!virDomainDefCheckABIStability(vm->def, config)) {
                virErrorPtr err = virGetLastError();

                if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_FORCE)) {
                    /* Re-spawn error using correct category. */
                    if (err->code == VIR_ERR_CONFIG_UNSUPPORTED)
                        virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY, "%s",
                                       err->str2);
                    goto cleanup;
                }

                virResetError(err);
                testDomainShutdownState(snapshot->domain, vm,
                                        VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT);
6494
                event = virDomainEventLifecycleNewFromObj(vm,
6495 6496
                            VIR_DOMAIN_EVENT_STOPPED,
                            VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
6497
                testObjectEventQueue(privconn, event);
6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508
                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. */
6509
                event = virDomainEventLifecycleNewFromObj(vm,
6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522
                                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;
6523
            event = virDomainEventLifecycleNewFromObj(vm,
6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536
                                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 */
6537
                event2 = virDomainEventLifecycleNewFromObj(vm,
6538 6539 6540 6541 6542
                                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 已提交
6543
            virObjectUnref(event);
6544 6545 6546 6547
            event = NULL;

            if (was_stopped) {
                /* Transition 2 */
6548
                event = virDomainEventLifecycleNewFromObj(vm,
6549 6550 6551 6552
                                VIR_DOMAIN_EVENT_STARTED,
                                VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            } else if (was_running) {
                /* Transition 8 */
6553
                event = virDomainEventLifecycleNewFromObj(vm,
6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565
                                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);
6566
            event = virDomainEventLifecycleNewFromObj(vm,
6567 6568 6569 6570 6571 6572 6573 6574 6575
                                    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;

6576
            testObjectEventQueue(privconn, event);
6577
            event = virDomainEventLifecycleNewFromObj(vm,
6578 6579 6580
                            VIR_DOMAIN_EVENT_STARTED,
                            VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            if (paused) {
6581
                event2 = virDomainEventLifecycleNewFromObj(vm,
6582 6583 6584 6585 6586 6587 6588 6589
                                VIR_DOMAIN_EVENT_SUSPENDED,
                                VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
            }
        }
    }

    vm->current_snapshot = snap;
    ret = 0;
6590
 cleanup:
6591
    if (event) {
6592
        testObjectEventQueue(privconn, event);
6593
        testObjectEventQueue(privconn, event2);
C
Cole Robinson 已提交
6594
    } else {
C
Cédric Bosdonnat 已提交
6595
        virObjectUnref(event2);
6596
    }
6597
    virDomainObjEndAPI(&vm);
6598 6599 6600 6601 6602

    return ret;
}


6603

6604
static virHypervisorDriver testHypervisorDriver = {
6605
    .name = "Test",
6606 6607 6608
    .connectOpen = testConnectOpen, /* 0.1.1 */
    .connectClose = testConnectClose, /* 0.1.1 */
    .connectGetVersion = testConnectGetVersion, /* 0.1.1 */
6609
    .connectGetHostname = testConnectGetHostname, /* 0.6.3 */
6610
    .connectGetMaxVcpus = testConnectGetMaxVcpus, /* 0.3.2 */
6611
    .nodeGetInfo = testNodeGetInfo, /* 0.1.1 */
6612 6613 6614 6615
    .connectGetCapabilities = testConnectGetCapabilities, /* 0.2.1 */
    .connectListDomains = testConnectListDomains, /* 0.1.1 */
    .connectNumOfDomains = testConnectNumOfDomains, /* 0.1.1 */
    .connectListAllDomains = testConnectListAllDomains, /* 0.9.13 */
6616
    .domainCreateXML = testDomainCreateXML, /* 0.1.4 */
6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630
    .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 */
6631 6632
    .domainGetState = testDomainGetState, /* 0.9.2 */
    .domainSave = testDomainSave, /* 0.3.2 */
6633
    .domainSaveFlags = testDomainSaveFlags, /* 0.9.4 */
6634
    .domainRestore = testDomainRestore, /* 0.3.2 */
6635
    .domainRestoreFlags = testDomainRestoreFlags, /* 0.9.4 */
6636
    .domainCoreDump = testDomainCoreDump, /* 0.3.2 */
6637
    .domainCoreDumpWithFormat = testDomainCoreDumpWithFormat, /* 1.2.3 */
6638
    .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */
6639 6640 6641 6642
    .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */
    .domainGetVcpusFlags = testDomainGetVcpusFlags, /* 0.8.5 */
    .domainPinVcpu = testDomainPinVcpu, /* 0.7.3 */
    .domainGetVcpus = testDomainGetVcpus, /* 0.7.3 */
6643
    .domainGetVcpuPinInfo = testDomainGetVcpuPinInfo, /* 1.2.18 */
6644 6645
    .domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
    .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
6646 6647
    .connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
    .connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
6648 6649 6650
    .domainCreate = testDomainCreate, /* 0.1.11 */
    .domainCreateWithFlags = testDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = testDomainDefineXML, /* 0.1.11 */
6651
    .domainDefineXMLFlags = testDomainDefineXMLFlags, /* 1.2.12 */
6652
    .domainUndefine = testDomainUndefine, /* 0.1.11 */
6653
    .domainUndefineFlags = testDomainUndefineFlags, /* 0.9.4 */
6654 6655 6656
    .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
    .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
    .domainGetSchedulerType = testDomainGetSchedulerType, /* 0.3.2 */
6657 6658 6659 6660
    .domainGetSchedulerParameters = testDomainGetSchedulerParameters, /* 0.3.2 */
    .domainGetSchedulerParametersFlags = testDomainGetSchedulerParametersFlags, /* 0.9.2 */
    .domainSetSchedulerParameters = testDomainSetSchedulerParameters, /* 0.3.2 */
    .domainSetSchedulerParametersFlags = testDomainSetSchedulerParametersFlags, /* 0.9.2 */
6661 6662 6663
    .domainBlockStats = testDomainBlockStats, /* 0.7.0 */
    .domainInterfaceStats = testDomainInterfaceStats, /* 0.7.0 */
    .nodeGetCellsFreeMemory = testNodeGetCellsFreeMemory, /* 0.4.2 */
6664 6665 6666 6667
    .connectDomainEventRegister = testConnectDomainEventRegister, /* 0.6.0 */
    .connectDomainEventDeregister = testConnectDomainEventDeregister, /* 0.6.0 */
    .connectIsEncrypted = testConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = testConnectIsSecure, /* 0.7.3 */
6668 6669 6670
    .domainIsActive = testDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = testDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = testDomainIsUpdated, /* 0.8.6 */
6671 6672 6673
    .connectDomainEventRegisterAny = testConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = testConnectDomainEventDeregisterAny, /* 0.8.0 */
    .connectIsAlive = testConnectIsAlive, /* 0.9.8 */
6674
    .nodeGetCPUMap = testNodeGetCPUMap, /* 1.0.0 */
6675
    .domainScreenshot = testDomainScreenshot, /* 1.0.5 */
6676 6677
    .domainGetMetadata = testDomainGetMetadata, /* 1.1.3 */
    .domainSetMetadata = testDomainSetMetadata, /* 1.1.3 */
6678
    .connectGetCPUModelNames = testConnectGetCPUModelNames, /* 1.1.3 */
6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695
    .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 */
6696 6697 6698
    .domainSnapshotCreateXML = testDomainSnapshotCreateXML, /* 1.1.4 */
    .domainRevertToSnapshot = testDomainRevertToSnapshot, /* 1.1.4 */
    .domainSnapshotDelete = testDomainSnapshotDelete, /* 1.1.4 */
6699

E
Eric Blake 已提交
6700
    .connectBaselineCPU = testConnectBaselineCPU, /* 1.2.0 */
6701 6702 6703
};

static virNetworkDriver testNetworkDriver = {
6704 6705 6706 6707 6708
    .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 */
6709 6710
    .connectNetworkEventRegisterAny = testConnectNetworkEventRegisterAny, /* 1.2.1 */
    .connectNetworkEventDeregisterAny = testConnectNetworkEventDeregisterAny, /* 1.2.1 */
6711 6712 6713 6714
    .networkLookupByUUID = testNetworkLookupByUUID, /* 0.3.2 */
    .networkLookupByName = testNetworkLookupByName, /* 0.3.2 */
    .networkCreateXML = testNetworkCreateXML, /* 0.3.2 */
    .networkDefineXML = testNetworkDefineXML, /* 0.3.2 */
6715
    .networkUndefine = testNetworkUndefine, /* 0.3.2 */
6716
    .networkUpdate = testNetworkUpdate, /* 0.10.2 */
6717
    .networkCreate = testNetworkCreate, /* 0.3.2 */
6718 6719 6720 6721 6722 6723 6724
    .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 */
6725 6726
};

L
Laine Stump 已提交
6727
static virInterfaceDriver testInterfaceDriver = {
6728 6729 6730 6731 6732 6733
    .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 */
6734 6735 6736 6737 6738 6739
    .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 */
6740 6741 6742
    .interfaceChangeBegin = testInterfaceChangeBegin,   /* 0.9.2 */
    .interfaceChangeCommit = testInterfaceChangeCommit,  /* 0.9.2 */
    .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */
L
Laine Stump 已提交
6743 6744 6745
};


6746
static virStorageDriver testStorageDriver = {
6747 6748 6749 6750 6751 6752
    .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 */
6753 6754 6755
    .storagePoolLookupByName = testStoragePoolLookupByName, /* 0.5.0 */
    .storagePoolLookupByUUID = testStoragePoolLookupByUUID, /* 0.5.0 */
    .storagePoolLookupByVolume = testStoragePoolLookupByVolume, /* 0.5.0 */
6756 6757
    .storagePoolCreateXML = testStoragePoolCreateXML, /* 0.5.0 */
    .storagePoolDefineXML = testStoragePoolDefineXML, /* 0.5.0 */
6758 6759
    .storagePoolBuild = testStoragePoolBuild, /* 0.5.0 */
    .storagePoolUndefine = testStoragePoolUndefine, /* 0.5.0 */
6760
    .storagePoolCreate = testStoragePoolCreate, /* 0.5.0 */
6761 6762 6763 6764 6765 6766 6767
    .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 */
6768
    .storagePoolNumOfVolumes = testStoragePoolNumOfVolumes, /* 0.5.0 */
6769 6770 6771
    .storagePoolListVolumes = testStoragePoolListVolumes, /* 0.5.0 */
    .storagePoolListAllVolumes = testStoragePoolListAllVolumes, /* 0.10.2 */

6772 6773 6774 6775 6776 6777 6778 6779 6780
    .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 */
6781 6782
    .storagePoolIsActive = testStoragePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = testStoragePoolIsPersistent, /* 0.7.3 */
6783 6784
};

6785
static virNodeDeviceDriver testNodeDeviceDriver = {
6786 6787 6788 6789 6790 6791 6792 6793 6794
    .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 */
6795 6796
};

6797 6798 6799 6800 6801 6802 6803 6804
static virConnectDriver testConnectDriver = {
    .hypervisorDriver = &testHypervisorDriver,
    .interfaceDriver = &testInterfaceDriver,
    .networkDriver = &testNetworkDriver,
    .nodeDeviceDriver = &testNodeDeviceDriver,
    .nwfilterDriver = NULL,
    .secretDriver = NULL,
    .storageDriver = &testStorageDriver,
6805 6806
};

6807 6808 6809 6810 6811 6812 6813 6814
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
6815 6816
    return virRegisterConnectDriver(&testConnectDriver,
                                    false);
6817
}