test_driver.c 192.2 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, false) < 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 1608
    virCheckFlags(VIR_DOMAIN_START_VALIDATE, NULL);

    if (flags & VIR_DOMAIN_START_VALIDATE)
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE;
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,
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 2458 2459
    for (i = 0; i < maxinfo; i++) {
        virDomainPinDefPtr pininfo;
        virBitmapPtr bitmap = NULL;
C
Cole Robinson 已提交
2460

2461 2462 2463
        pininfo = virDomainPinFind(def->cputune.vcpupin,
                                   def->cputune.nvcpupin,
                                   i);
C
Cole Robinson 已提交
2464

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

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

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

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

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

C
Cole Robinson 已提交
2490 2491 2492 2493 2494 2495
static int testDomainPinVcpu(virDomainPtr domain,
                             unsigned int vcpu,
                             unsigned char *cpumap,
                             int maplen)
{
    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
    if (vcpu > virDomainDefGetVcpus(privdom->def)) {
2511 2512 2513
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested vcpu '%d' is not present in the domain"),
                       vcpu);
C
Cole Robinson 已提交
2514 2515 2516
        goto cleanup;
    }

2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529
    if (!def->cputune.vcpupin) {
        if (VIR_ALLOC(def->cputune.vcpupin) < 0)
            goto cleanup;
        def->cputune.nvcpupin = 0;
    }
    if (virDomainPinAdd(&def->cputune.vcpupin,
                        &def->cputune.nvcpupin,
                        cpumap,
                        maplen,
                        vcpu) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to update or add vcpupin"));
        goto cleanup;
C
Cole Robinson 已提交
2530 2531 2532
    }

    ret = 0;
2533
 cleanup:
2534
    virDomainObjEndAPI(&privdom);
C
Cole Robinson 已提交
2535 2536 2537
    return ret;
}

2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564
static int
testDomainGetVcpuPinInfo(virDomainPtr dom,
                        int ncpumaps,
                        unsigned char *cpumaps,
                        int maplen,
                        unsigned int flags)
{
    testDriverPtr privconn = dom->conn->privateData;
    virDomainObjPtr privdom;
    virDomainDefPtr def;
    int ret = -1, hostcpus, vcpu;
    virBitmapPtr allcpumap = NULL;

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

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

    hostcpus = VIR_NODEINFO_MAXCPUS(privconn->nodeInfo);

    if (!(allcpumap = virBitmapNew(hostcpus)))
        goto cleanup;

    virBitmapSetAll(allcpumap);

    /* Clamp to actual number of vcpus */
2565 2566
    if (ncpumaps > virDomainDefGetVcpus(def))
        ncpumaps = virDomainDefGetVcpus(def);
2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591

    for (vcpu = 0; vcpu < ncpumaps; vcpu++) {
        virDomainPinDefPtr pininfo;
        virBitmapPtr bitmap = NULL;

        pininfo = virDomainPinFind(def->cputune.vcpupin,
                                   def->cputune.nvcpupin,
                                   vcpu);

        if (pininfo && pininfo->cpumask)
            bitmap = pininfo->cpumask;
        else
            bitmap = allcpumap;

        virBitmapToDataBuf(bitmap, VIR_GET_CPUMAP(cpumaps, maplen, vcpu), maplen);
    }

    ret = ncpumaps;

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

2592
static char *testDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
2593
{
2594
    virDomainDefPtr def;
2595
    virDomainObjPtr privdom;
2596 2597
    char *ret = NULL;

2598 2599
    /* Flags checked by virDomainDefFormat */

2600 2601
    if (!(privdom = testDomObjFromDomain(domain)))
        return NULL;
2602

2603 2604
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
2605

2606
    ret = virDomainDefFormat(def, virDomainDefFormatConvertXMLFlags(flags));
2607

2608
    virDomainObjEndAPI(&privdom);
2609
    return ret;
2610
}
2611

2612 2613
static int testConnectNumOfDefinedDomains(virConnectPtr conn)
{
2614
    testDriverPtr privconn = conn->privateData;
2615

2616
    return virDomainObjListNumOfDomains(privconn->domains, false, NULL, NULL);
2617 2618
}

2619 2620
static int testConnectListDefinedDomains(virConnectPtr conn,
                                         char **const names,
2621 2622
                                         int maxnames)
{
2623

2624
    testDriverPtr privconn = conn->privateData;
2625 2626

    memset(names, 0, sizeof(*names)*maxnames);
2627 2628
    return virDomainObjListGetInactiveNames(privconn->domains, names, maxnames,
                                            NULL, NULL);
2629 2630
}

2631 2632 2633
static virDomainPtr testDomainDefineXMLFlags(virConnectPtr conn,
                                             const char *xml,
                                             unsigned int flags)
2634
{
2635
    testDriverPtr privconn = conn->privateData;
2636
    virDomainPtr ret = NULL;
2637
    virDomainDefPtr def;
2638
    virDomainObjPtr dom = NULL;
2639
    virObjectEventPtr event = NULL;
2640
    virDomainDefPtr oldDef = NULL;
2641 2642 2643
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;

    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
2644

2645 2646
    if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE;
2647

2648
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
2649
                                       parse_flags)) == NULL)
2650
        goto cleanup;
2651

2652
    if (testDomainGenerateIfnames(def) < 0)
2653
        goto cleanup;
2654
    if (!(dom = virDomainObjListAdd(privconn->domains,
2655
                                    def,
2656
                                    privconn->xmlopt,
2657 2658
                                    0,
                                    &oldDef)))
2659
        goto cleanup;
2660
    def = NULL;
2661
    dom->persistent = 1;
2662

2663
    event = virDomainEventLifecycleNewFromObj(dom,
2664
                                     VIR_DOMAIN_EVENT_DEFINED,
2665
                                     !oldDef ?
2666 2667
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
2668

2669
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
2670
    if (ret)
2671
        ret->id = dom->def->id;
2672

2673
 cleanup:
2674
    virDomainDefFree(def);
2675
    virDomainDefFree(oldDef);
2676
    if (dom)
2677
        virObjectUnlock(dom);
2678
    testObjectEventQueue(privconn, event);
2679
    return ret;
2680 2681
}

2682 2683 2684 2685 2686 2687
static virDomainPtr
testDomainDefineXML(virConnectPtr conn, const char *xml)
{
    return testDomainDefineXMLFlags(conn, xml, 0);
}

2688 2689 2690 2691 2692
static char *testDomainGetMetadata(virDomainPtr dom,
                                   int type,
                                   const char *uri,
                                   unsigned int flags)
{
2693
    testDriverPtr privconn = dom->conn->privateData;
2694
    virDomainObjPtr privdom;
2695
    char *ret;
2696 2697 2698 2699

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, NULL);

2700 2701
    if (!(privdom = testDomObjFromDomain(dom)))
        return NULL;
2702 2703 2704 2705

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

2706
    virDomainObjEndAPI(&privdom);
2707 2708 2709 2710 2711 2712 2713 2714 2715 2716
    return ret;
}

static int testDomainSetMetadata(virDomainPtr dom,
                                 int type,
                                 const char *metadata,
                                 const char *key,
                                 const char *uri,
                                 unsigned int flags)
{
2717
    testDriverPtr privconn = dom->conn->privateData;
2718
    virDomainObjPtr privdom;
2719
    int ret;
2720 2721 2722 2723

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

2724 2725
    if (!(privdom = testDomObjFromDomain(dom)))
        return -1;
2726 2727 2728

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

2731
    virDomainObjEndAPI(&privdom);
2732 2733 2734 2735
    return ret;
}


2736 2737
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
2738 2739
                                      int startCell, int maxCells)
{
2740
    testDriverPtr privconn = conn->privateData;
2741 2742
    int cell;
    size_t i;
2743
    int ret = -1;
2744

2745
    testDriverLock(privconn);
2746
    if (startCell > privconn->numCells) {
2747 2748
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("Range exceeds available cells"));
2749
        goto cleanup;
2750 2751
    }

2752 2753 2754 2755
    for (cell = startCell, i = 0;
         (cell < privconn->numCells && i < maxCells);
         ++cell, ++i) {
        freemems[i] = privconn->cells[cell].mem;
2756
    }
2757
    ret = i;
2758

2759
 cleanup:
2760
    testDriverUnlock(privconn);
2761
    return ret;
2762 2763 2764
}


2765 2766
static int testDomainCreateWithFlags(virDomainPtr domain, unsigned int flags)
{
2767
    testDriverPtr privconn = domain->conn->privateData;
2768
    virDomainObjPtr privdom;
2769
    virObjectEventPtr event = NULL;
2770
    int ret = -1;
2771

2772 2773
    virCheckFlags(0, -1);

2774
    testDriverLock(privconn);
2775

2776
    if (!(privdom = testDomObjFromDomain(domain)))
2777
        goto cleanup;
2778

J
Jiri Denemark 已提交
2779
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_SHUTOFF) {
2780 2781
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Domain '%s' is already running"), domain->name);
2782
        goto cleanup;
2783 2784
    }

2785
    if (testDomainStartState(privconn, privdom,
J
Jiri Denemark 已提交
2786
                             VIR_DOMAIN_RUNNING_BOOTED) < 0)
2787 2788 2789
        goto cleanup;
    domain->id = privdom->def->id;

2790
    event = virDomainEventLifecycleNewFromObj(privdom,
2791 2792
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
2793
    ret = 0;
2794

2795
 cleanup:
2796
    virDomainObjEndAPI(&privdom);
2797
    testObjectEventQueue(privconn, event);
2798
    testDriverUnlock(privconn);
2799
    return ret;
2800 2801
}

2802 2803
static int testDomainCreate(virDomainPtr domain)
{
2804 2805 2806
    return testDomainCreateWithFlags(domain, 0);
}

2807 2808 2809
static int testDomainUndefineFlags(virDomainPtr domain,
                                   unsigned int flags)
{
2810
    testDriverPtr privconn = domain->conn->privateData;
2811
    virDomainObjPtr privdom;
2812
    virObjectEventPtr event = NULL;
2813
    int nsnapshots;
2814
    int ret = -1;
2815

2816 2817
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
                  VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
2818

2819

2820
    if (!(privdom = testDomObjFromDomain(domain)))
2821
        goto cleanup;
2822

C
Cole Robinson 已提交
2823 2824 2825 2826 2827 2828 2829 2830
    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;
    }

2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848
    /* 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. */
    }

2849
    event = virDomainEventLifecycleNewFromObj(privdom,
2850 2851
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
C
Cole Robinson 已提交
2852 2853
    privdom->hasManagedSave = false;

2854
    if (virDomainObjIsActive(privdom))
2855
        privdom->persistent = 0;
2856 2857
    else
        virDomainObjListRemove(privconn->domains, privdom);
2858

2859
    ret = 0;
2860

2861
 cleanup:
2862
    virDomainObjEndAPI(&privdom);
2863
    testObjectEventQueue(privconn, event);
2864
    return ret;
2865 2866
}

2867 2868 2869 2870 2871
static int testDomainUndefine(virDomainPtr domain)
{
    return testDomainUndefineFlags(domain, 0);
}

2872 2873 2874
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
2875 2876
    virDomainObjPtr privdom;

2877 2878
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2879

2880
    *autostart = privdom->autostart;
2881

2882
    virDomainObjEndAPI(&privdom);
2883
    return 0;
2884 2885 2886 2887 2888 2889
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
2890 2891
    virDomainObjPtr privdom;

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

2895
    privdom->autostart = autostart ? 1 : 0;
2896

2897
    virDomainObjEndAPI(&privdom);
2898
    return 0;
2899
}
2900

2901
static char *testDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED,
2902 2903
                                        int *nparams)
{
2904 2905
    char *type = NULL;

2906 2907 2908
    if (nparams)
        *nparams = 1;

2909
    ignore_value(VIR_STRDUP(type, "fair"));
2910

2911 2912 2913
    return type;
}

2914
static int
2915 2916 2917 2918
testDomainGetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int *nparams,
                                      unsigned int flags)
2919
{
2920
    virDomainObjPtr privdom;
2921
    int ret = -1;
2922

2923 2924
    virCheckFlags(0, -1);

2925 2926
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2927

2928 2929
    if (virTypedParameterAssign(params, VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, 50) < 0)
2930
        goto cleanup;
2931 2932
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
2933 2934

    *nparams = 1;
2935 2936
    ret = 0;

2937
 cleanup:
2938
    virDomainObjEndAPI(&privdom);
2939
    return ret;
2940
}
2941

2942
static int
2943 2944 2945
testDomainGetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int *nparams)
2946
{
2947
    return testDomainGetSchedulerParametersFlags(domain, params, nparams, 0);
2948
}
2949

2950
static int
2951 2952 2953 2954
testDomainSetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int nparams,
                                      unsigned int flags)
2955
{
2956
    virDomainObjPtr privdom;
2957 2958
    int ret = -1;
    size_t i;
2959

2960
    virCheckFlags(0, -1);
2961 2962 2963 2964
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
2965
        return -1;
2966

2967 2968
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2969

2970
    for (i = 0; i < nparams; i++) {
2971 2972 2973
        if (STREQ(params[i].field, VIR_DOMAIN_SCHEDULER_WEIGHT)) {
            /* XXX */
            /*privdom->weight = params[i].value.ui;*/
2974
        }
2975
    }
2976

2977 2978
    ret = 0;

2979
    virDomainObjEndAPI(&privdom);
2980
    return ret;
2981 2982
}

2983
static int
2984 2985 2986
testDomainSetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int nparams)
2987
{
2988
    return testDomainSetSchedulerParametersFlags(domain, params, nparams, 0);
2989 2990
}

2991 2992
static int testDomainBlockStats(virDomainPtr domain,
                                const char *path,
2993
                                virDomainBlockStatsPtr stats)
2994 2995 2996 2997
{
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
2998
    int ret = -1;
2999

3000 3001 3002 3003 3004 3005
    if (!*path) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("summary statistics are not supported yet"));
        return ret;
    }

3006 3007
    if (!(privdom = testDomObjFromDomain(domain)))
        return ret;
3008

3009
    if (virDomainDiskIndexByName(privdom->def, path, false) < 0) {
3010 3011
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path: %s"), path);
3012 3013 3014 3015
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
3016
        virReportSystemError(errno,
3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029
                             "%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;
3030
 error:
3031
    virDomainObjEndAPI(&privdom);
3032 3033 3034 3035 3036
    return ret;
}

static int testDomainInterfaceStats(virDomainPtr domain,
                                    const char *path,
3037
                                    virDomainInterfaceStatsPtr stats)
3038 3039 3040 3041
{
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
3042 3043
    size_t i;
    int found = 0, ret = -1;
3044

3045 3046
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3047

3048
    for (i = 0; i < privdom->def->nnets; i++) {
3049
        if (privdom->def->nets[i]->ifname &&
3050
            STREQ(privdom->def->nets[i]->ifname, path)) {
3051 3052 3053 3054 3055 3056
            found = 1;
            break;
        }
    }

    if (!found) {
3057 3058
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path, '%s' is not a known interface"), path);
3059 3060 3061 3062
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
3063
        virReportSystemError(errno,
3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079
                             "%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;
3080
 error:
3081
    virDomainObjEndAPI(&privdom);
3082 3083 3084
    return ret;
}

3085

3086 3087
static virNetworkPtr testNetworkLookupByUUID(virConnectPtr conn,
                                             const unsigned char *uuid)
3088
{
3089
    testDriverPtr privconn = conn->privateData;
3090
    virNetworkObjPtr net;
3091
    virNetworkPtr ret = NULL;
3092

3093
    net = virNetworkObjFindByUUID(privconn->networks, uuid);
3094
    if (net == NULL) {
3095
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3096
        goto cleanup;
3097 3098
    }

3099 3100
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

3101
 cleanup:
3102
    virNetworkObjEndAPI(&net);
3103
    return ret;
3104
}
3105

3106
static virNetworkPtr testNetworkLookupByName(virConnectPtr conn,
3107
                                             const char *name)
3108
{
3109
    testDriverPtr privconn = conn->privateData;
3110 3111
    virNetworkObjPtr net;
    virNetworkPtr ret = NULL;
3112

3113
    net = virNetworkObjFindByName(privconn->networks, name);
3114
    if (net == NULL) {
3115
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3116
        goto cleanup;
3117 3118
    }

3119 3120
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

3121
 cleanup:
3122
    virNetworkObjEndAPI(&net);
3123
    return ret;
3124 3125 3126
}


3127 3128
static int testConnectNumOfNetworks(virConnectPtr conn)
{
3129
    testDriverPtr privconn = conn->privateData;
3130
    int numActive;
3131

3132 3133
    numActive = virNetworkObjListNumOfNetworks(privconn->networks,
                                               true, NULL, conn);
3134
    return numActive;
3135 3136
}

3137
static int testConnectListNetworks(virConnectPtr conn, char **const names, int nnames) {
3138
    testDriverPtr privconn = conn->privateData;
3139
    int n;
3140

3141 3142
    n = virNetworkObjListGetNames(privconn->networks,
                                  true, names, nnames, NULL, conn);
3143
    return n;
3144 3145
}

3146 3147
static int testConnectNumOfDefinedNetworks(virConnectPtr conn)
{
3148
    testDriverPtr privconn = conn->privateData;
3149
    int numInactive;
3150

3151 3152
    numInactive = virNetworkObjListNumOfNetworks(privconn->networks,
                                                 false, NULL, conn);
3153
    return numInactive;
3154 3155
}

3156
static int testConnectListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
3157
    testDriverPtr privconn = conn->privateData;
3158
    int n;
3159

3160 3161
    n = virNetworkObjListGetNames(privconn->networks,
                                  false, names, nnames, NULL, conn);
3162
    return n;
3163 3164
}

3165
static int
3166
testConnectListAllNetworks(virConnectPtr conn,
3167 3168 3169
                           virNetworkPtr **nets,
                           unsigned int flags)
{
3170
    testDriverPtr privconn = conn->privateData;
3171 3172 3173

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

3174
    return virNetworkObjListExport(conn, privconn->networks, nets, NULL, flags);
3175
}
3176 3177 3178

static int testNetworkIsActive(virNetworkPtr net)
{
3179
    testDriverPtr privconn = net->conn->privateData;
3180 3181 3182
    virNetworkObjPtr obj;
    int ret = -1;

3183
    obj = virNetworkObjFindByUUID(privconn->networks, net->uuid);
3184
    if (!obj) {
3185
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3186 3187 3188 3189
        goto cleanup;
    }
    ret = virNetworkObjIsActive(obj);

3190
 cleanup:
3191
    virNetworkObjEndAPI(&obj);
3192 3193 3194 3195 3196
    return ret;
}

static int testNetworkIsPersistent(virNetworkPtr net)
{
3197
    testDriverPtr privconn = net->conn->privateData;
3198 3199 3200
    virNetworkObjPtr obj;
    int ret = -1;

3201
    obj = virNetworkObjFindByUUID(privconn->networks, net->uuid);
3202
    if (!obj) {
3203
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3204 3205 3206 3207
        goto cleanup;
    }
    ret = obj->persistent;

3208
 cleanup:
3209
    virNetworkObjEndAPI(&obj);
3210 3211 3212 3213
    return ret;
}


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

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

3225 3226 3227
    if (!(net = virNetworkAssignDef(privconn->networks, def,
                                    VIR_NETWORK_OBJ_LIST_ADD_LIVE |
                                    VIR_NETWORK_OBJ_LIST_ADD_CHECK_LIVE)))
3228 3229
        goto cleanup;
    def = NULL;
3230
    net->active = 1;
3231

3232
    event = virNetworkEventLifecycleNew(net->def->name, net->def->uuid,
3233 3234
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3235

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

3238
 cleanup:
3239
    virNetworkDefFree(def);
3240
    testObjectEventQueue(privconn, event);
3241
    virNetworkObjEndAPI(&net);
3242
    return ret;
3243 3244
}

3245
static
3246
virNetworkPtr testNetworkDefineXML(virConnectPtr conn, const char *xml)
3247
{
3248
    testDriverPtr privconn = conn->privateData;
3249
    virNetworkDefPtr def;
3250
    virNetworkObjPtr net = NULL;
3251
    virNetworkPtr ret = NULL;
3252
    virObjectEventPtr event = NULL;
3253

3254
    if ((def = virNetworkDefParseString(xml)) == NULL)
3255
        goto cleanup;
3256

3257
    if (!(net = virNetworkAssignDef(privconn->networks, def, 0)))
3258 3259
        goto cleanup;
    def = NULL;
3260

3261
    event = virNetworkEventLifecycleNew(net->def->name, net->def->uuid,
3262 3263
                                        VIR_NETWORK_EVENT_DEFINED,
                                        0);
3264

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

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

3274 3275
static int testNetworkUndefine(virNetworkPtr network)
{
3276
    testDriverPtr privconn = network->conn->privateData;
3277
    virNetworkObjPtr privnet;
3278
    int ret = -1;
3279
    virObjectEventPtr event = NULL;
3280

3281
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3282 3283

    if (privnet == NULL) {
3284
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3285
        goto cleanup;
3286
    }
3287

D
Daniel P. Berrange 已提交
3288
    if (virNetworkObjIsActive(privnet)) {
3289 3290
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is still running"), network->name);
3291
        goto cleanup;
3292 3293
    }

3294
    event = virNetworkEventLifecycleNew(network->name, network->uuid,
3295 3296
                                        VIR_NETWORK_EVENT_UNDEFINED,
                                        0);
3297

3298
    virNetworkRemoveInactive(privconn->networks, privnet);
3299
    ret = 0;
3300

3301
 cleanup:
3302
    testObjectEventQueue(privconn, event);
3303
    virNetworkObjEndAPI(&privnet);
3304
    return ret;
3305 3306
}

3307 3308 3309 3310 3311 3312 3313 3314
static int
testNetworkUpdate(virNetworkPtr net,
                  unsigned int command,
                  unsigned int section,
                  int parentIndex,
                  const char *xml,
                  unsigned int flags)
{
3315
    testDriverPtr privconn = net->conn->privateData;
3316 3317 3318 3319 3320 3321 3322
    virNetworkObjPtr network = NULL;
    int isActive, ret = -1;

    virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
                  VIR_NETWORK_UPDATE_AFFECT_CONFIG,
                  -1);

3323
    network = virNetworkObjFindByUUID(privconn->networks, net->uuid);
3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347
    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;
3348
 cleanup:
3349
    virNetworkObjEndAPI(&network);
3350 3351 3352
    return ret;
}

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

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

D
Daniel P. Berrange 已提交
3366
    if (virNetworkObjIsActive(privnet)) {
3367 3368
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is already running"), network->name);
3369
        goto cleanup;
3370 3371
    }

3372
    privnet->active = 1;
3373
    event = virNetworkEventLifecycleNew(privnet->def->name, privnet->def->uuid,
3374 3375
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3376
    ret = 0;
3377

3378
 cleanup:
3379
    testObjectEventQueue(privconn, event);
3380
    virNetworkObjEndAPI(&privnet);
3381
    return ret;
3382 3383
}

3384 3385
static int testNetworkDestroy(virNetworkPtr network)
{
3386
    testDriverPtr privconn = network->conn->privateData;
3387
    virNetworkObjPtr privnet;
3388
    int ret = -1;
3389
    virObjectEventPtr event = NULL;
3390

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

3397
    privnet->active = 0;
3398
    event = virNetworkEventLifecycleNew(privnet->def->name, privnet->def->uuid,
3399 3400
                                        VIR_NETWORK_EVENT_STOPPED,
                                        0);
3401
    if (!privnet->persistent)
3402
        virNetworkRemoveInactive(privconn->networks, privnet);
3403

3404 3405
    ret = 0;

3406
 cleanup:
3407
    testObjectEventQueue(privconn, event);
3408
    virNetworkObjEndAPI(&privnet);
3409
    return ret;
3410 3411
}

3412
static char *testNetworkGetXMLDesc(virNetworkPtr network,
E
Eric Blake 已提交
3413
                                   unsigned int flags)
3414
{
3415
    testDriverPtr privconn = network->conn->privateData;
3416
    virNetworkObjPtr privnet;
3417
    char *ret = NULL;
3418

E
Eric Blake 已提交
3419 3420
    virCheckFlags(0, NULL);

3421
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3422
    if (privnet == NULL) {
3423
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3424
        goto cleanup;
3425
    }
3426

3427
    ret = virNetworkDefFormat(privnet->def, flags);
3428

3429
 cleanup:
3430
    virNetworkObjEndAPI(&privnet);
3431
    return ret;
3432 3433 3434
}

static char *testNetworkGetBridgeName(virNetworkPtr network) {
3435
    testDriverPtr privconn = network->conn->privateData;
3436
    char *bridge = NULL;
3437 3438
    virNetworkObjPtr privnet;

3439
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3440
    if (privnet == NULL) {
3441
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3442
        goto cleanup;
3443 3444
    }

3445
    if (!(privnet->def->bridge)) {
3446 3447 3448
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("network '%s' does not have a bridge name."),
                       privnet->def->name);
3449 3450 3451
        goto cleanup;
    }

3452
    ignore_value(VIR_STRDUP(bridge, privnet->def->bridge));
3453

3454
 cleanup:
3455
    virNetworkObjEndAPI(&privnet);
3456 3457 3458 3459
    return bridge;
}

static int testNetworkGetAutostart(virNetworkPtr network,
3460 3461
                                   int *autostart)
{
3462
    testDriverPtr privconn = network->conn->privateData;
3463
    virNetworkObjPtr privnet;
3464
    int ret = -1;
3465

3466
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3467
    if (privnet == NULL) {
3468
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3469
        goto cleanup;
3470 3471
    }

3472
    *autostart = privnet->autostart;
3473 3474
    ret = 0;

3475
 cleanup:
3476
    virNetworkObjEndAPI(&privnet);
3477
    return ret;
3478 3479 3480
}

static int testNetworkSetAutostart(virNetworkPtr network,
3481 3482
                                   int autostart)
{
3483
    testDriverPtr privconn = network->conn->privateData;
3484
    virNetworkObjPtr privnet;
3485
    int ret = -1;
3486

3487
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3488
    if (privnet == NULL) {
3489
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3490
        goto cleanup;
3491 3492
    }

3493
    privnet->autostart = autostart ? 1 : 0;
3494 3495
    ret = 0;

3496
 cleanup:
3497
    virNetworkObjEndAPI(&privnet);
3498
    return ret;
3499
}
3500

C
Cole Robinson 已提交
3501

L
Laine Stump 已提交
3502 3503 3504 3505 3506
/*
 * Physical host interface routines
 */


3507
static int testConnectNumOfInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3508
{
3509
    testDriverPtr privconn = conn->privateData;
3510 3511
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3512 3513

    testDriverLock(privconn);
3514
    for (i = 0; (i < privconn->ifaces.count); i++) {
L
Laine Stump 已提交
3515
        virInterfaceObjLock(privconn->ifaces.objs[i]);
3516
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i]))
L
Laine Stump 已提交
3517 3518 3519 3520 3521 3522 3523
            count++;
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3524
static int testConnectListInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3525
{
3526
    testDriverPtr privconn = conn->privateData;
3527 3528
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3529 3530 3531

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
3532
    for (i = 0; (i < privconn->ifaces.count) && (n < nnames); i++) {
L
Laine Stump 已提交
3533
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3534
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
3535
            if (VIR_STRDUP(names[n++], privconn->ifaces.objs[i]->def->name) < 0) {
L
Laine Stump 已提交
3536
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
3537
                goto error;
L
Laine Stump 已提交
3538 3539 3540 3541 3542 3543 3544 3545
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

3546
 error:
3547
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3548 3549 3550 3551 3552
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

3553
static int testConnectNumOfDefinedInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3554
{
3555
    testDriverPtr privconn = conn->privateData;
3556 3557
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3558 3559

    testDriverLock(privconn);
3560
    for (i = 0; i < privconn->ifaces.count; i++) {
L
Laine Stump 已提交
3561
        virInterfaceObjLock(privconn->ifaces.objs[i]);
3562
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i]))
L
Laine Stump 已提交
3563 3564 3565 3566 3567 3568 3569
            count++;
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3570
static int testConnectListDefinedInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3571
{
3572
    testDriverPtr privconn = conn->privateData;
3573 3574
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3575 3576 3577

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
3578
    for (i = 0; (i < privconn->ifaces.count) && (n < nnames); i++) {
L
Laine Stump 已提交
3579
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3580
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
3581
            if (VIR_STRDUP(names[n++], privconn->ifaces.objs[i]->def->name) < 0) {
L
Laine Stump 已提交
3582
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
3583
                goto error;
L
Laine Stump 已提交
3584 3585 3586 3587 3588 3589 3590 3591
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

3592
 error:
3593
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3594 3595 3596 3597 3598
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

3599
static virInterfacePtr testInterfaceLookupByName(virConnectPtr conn,
L
Laine Stump 已提交
3600 3601
                                                 const char *name)
{
3602
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3603 3604 3605 3606 3607 3608 3609 3610
    virInterfaceObjPtr iface;
    virInterfacePtr ret = NULL;

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

    if (iface == NULL) {
3611
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3612 3613 3614 3615 3616
        goto cleanup;
    }

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

3617
 cleanup:
L
Laine Stump 已提交
3618 3619 3620 3621 3622
    if (iface)
        virInterfaceObjUnlock(iface);
    return ret;
}

3623
static virInterfacePtr testInterfaceLookupByMACString(virConnectPtr conn,
L
Laine Stump 已提交
3624 3625
                                                      const char *mac)
{
3626
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3627 3628 3629 3630 3631 3632 3633 3634 3635
    virInterfaceObjPtr iface;
    int ifacect;
    virInterfacePtr ret = NULL;

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

    if (ifacect == 0) {
3636
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3637 3638 3639 3640
        goto cleanup;
    }

    if (ifacect > 1) {
3641
        virReportError(VIR_ERR_MULTIPLE_INTERFACES, NULL);
L
Laine Stump 已提交
3642 3643 3644 3645 3646
        goto cleanup;
    }

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

3647
 cleanup:
L
Laine Stump 已提交
3648 3649 3650 3651 3652
    if (iface)
        virInterfaceObjUnlock(iface);
    return ret;
}

3653 3654
static int testInterfaceIsActive(virInterfacePtr iface)
{
3655
    testDriverPtr privconn = iface->conn->privateData;
3656 3657 3658 3659 3660 3661 3662
    virInterfaceObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virInterfaceFindByName(&privconn->ifaces, iface->name);
    testDriverUnlock(privconn);
    if (!obj) {
3663
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
3664 3665 3666 3667
        goto cleanup;
    }
    ret = virInterfaceObjIsActive(obj);

3668
 cleanup:
3669 3670 3671 3672 3673
    if (obj)
        virInterfaceObjUnlock(obj);
    return ret;
}

3674
static int testInterfaceChangeBegin(virConnectPtr conn,
E
Eric Blake 已提交
3675
                                    unsigned int flags)
3676
{
3677
    testDriverPtr privconn = conn->privateData;
3678 3679
    int ret = -1;

E
Eric Blake 已提交
3680 3681
    virCheckFlags(0, -1);

3682 3683
    testDriverLock(privconn);
    if (privconn->transaction_running) {
3684
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3685
                       _("there is another transaction running."));
3686 3687 3688 3689 3690 3691 3692 3693 3694 3695
        goto cleanup;
    }

    privconn->transaction_running = true;

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

    ret = 0;
3696
 cleanup:
3697 3698 3699 3700 3701
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceChangeCommit(virConnectPtr conn,
E
Eric Blake 已提交
3702
                                     unsigned int flags)
3703
{
3704
    testDriverPtr privconn = conn->privateData;
3705 3706
    int ret = -1;

E
Eric Blake 已提交
3707 3708
    virCheckFlags(0, -1);

3709 3710 3711
    testDriverLock(privconn);

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

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

    ret = 0;

3723
 cleanup:
3724 3725 3726 3727 3728 3729
    testDriverUnlock(privconn);

    return ret;
}

static int testInterfaceChangeRollback(virConnectPtr conn,
E
Eric Blake 已提交
3730
                                       unsigned int flags)
3731
{
3732
    testDriverPtr privconn = conn->privateData;
3733 3734
    int ret = -1;

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

3737 3738 3739
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3740
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3741 3742
                       _("no transaction running, "
                         "nothing to rollback."));
3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755
        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;

3756
 cleanup:
3757 3758 3759
    testDriverUnlock(privconn);
    return ret;
}
3760

L
Laine Stump 已提交
3761
static char *testInterfaceGetXMLDesc(virInterfacePtr iface,
E
Eric Blake 已提交
3762
                                     unsigned int flags)
L
Laine Stump 已提交
3763
{
3764
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3765 3766 3767
    virInterfaceObjPtr privinterface;
    char *ret = NULL;

E
Eric Blake 已提交
3768 3769
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
3770 3771 3772 3773 3774 3775
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);
    testDriverUnlock(privconn);

    if (privinterface == NULL) {
3776
        virReportError(VIR_ERR_NO_INTERFACE, __FUNCTION__);
L
Laine Stump 已提交
3777 3778 3779
        goto cleanup;
    }

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

3782
 cleanup:
L
Laine Stump 已提交
3783 3784 3785 3786 3787 3788 3789
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    return ret;
}


static virInterfacePtr testInterfaceDefineXML(virConnectPtr conn, const char *xmlStr,
E
Eric Blake 已提交
3790
                                              unsigned int flags)
L
Laine Stump 已提交
3791
{
3792
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3793 3794 3795 3796
    virInterfaceDefPtr def;
    virInterfaceObjPtr iface = NULL;
    virInterfacePtr ret = NULL;

E
Eric Blake 已提交
3797 3798
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
3799
    testDriverLock(privconn);
3800
    if ((def = virInterfaceDefParseString(xmlStr)) == NULL)
L
Laine Stump 已提交
3801 3802
        goto cleanup;

3803
    if ((iface = virInterfaceAssignDef(&privconn->ifaces, def)) == NULL)
L
Laine Stump 已提交
3804 3805 3806 3807 3808
        goto cleanup;
    def = NULL;

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

3809
 cleanup:
L
Laine Stump 已提交
3810 3811 3812 3813 3814 3815 3816 3817 3818
    virInterfaceDefFree(def);
    if (iface)
        virInterfaceObjUnlock(iface);
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceUndefine(virInterfacePtr iface)
{
3819
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3820 3821 3822 3823 3824 3825 3826 3827
    virInterfaceObjPtr privinterface;
    int ret = -1;

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

    if (privinterface == NULL) {
3828
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3829 3830 3831 3832 3833 3834 3835
        goto cleanup;
    }

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

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

static int testInterfaceCreate(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 = 1;
    ret = 0;

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

static int testInterfaceDestroy(virInterfacePtr iface,
E
Eric Blake 已提交
3875
                                unsigned int flags)
L
Laine Stump 已提交
3876
{
3877
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3878 3879 3880
    virInterfaceObjPtr privinterface;
    int ret = -1;

E
Eric Blake 已提交
3881 3882
    virCheckFlags(0, -1);

L
Laine Stump 已提交
3883 3884 3885 3886 3887
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);

    if (privinterface == NULL) {
3888
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3889 3890 3891 3892
        goto cleanup;
    }

    if (privinterface->active == 0) {
3893
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
3894 3895 3896 3897 3898 3899
        goto cleanup;
    }

    privinterface->active = 0;
    ret = 0;

3900
 cleanup:
L
Laine Stump 已提交
3901 3902 3903 3904 3905 3906 3907 3908
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    testDriverUnlock(privconn);
    return ret;
}



C
Cole Robinson 已提交
3909 3910 3911 3912
/*
 * Storage Driver routines
 */

3913

3914 3915
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool)
{
C
Cole Robinson 已提交
3916 3917 3918 3919 3920

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

3921
    return VIR_STRDUP(pool->configFile, "");
C
Cole Robinson 已提交
3922 3923
}

3924

C
Cole Robinson 已提交
3925 3926
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
3927 3928
                            const unsigned char *uuid)
{
3929
    testDriverPtr privconn = conn->privateData;
3930 3931
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3932

3933
    testDriverLock(privconn);
3934
    pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid);
3935
    testDriverUnlock(privconn);
3936 3937

    if (pool == NULL) {
3938
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
3939
        goto cleanup;
C
Cole Robinson 已提交
3940 3941
    }

3942 3943
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
3944

3945
 cleanup:
3946 3947
    if (pool)
        virStoragePoolObjUnlock(pool);
3948
    return ret;
C
Cole Robinson 已提交
3949 3950 3951 3952
}

static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
3953 3954
                            const char *name)
{
3955
    testDriverPtr privconn = conn->privateData;
3956 3957
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3958

3959
    testDriverLock(privconn);
3960
    pool = virStoragePoolObjFindByName(&privconn->pools, name);
3961
    testDriverUnlock(privconn);
3962 3963

    if (pool == NULL) {
3964
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
3965
        goto cleanup;
C
Cole Robinson 已提交
3966 3967
    }

3968 3969
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
3970

3971
 cleanup:
3972 3973
    if (pool)
        virStoragePoolObjUnlock(pool);
3974
    return ret;
C
Cole Robinson 已提交
3975 3976 3977
}

static virStoragePoolPtr
3978 3979
testStoragePoolLookupByVolume(virStorageVolPtr vol)
{
C
Cole Robinson 已提交
3980 3981 3982 3983
    return testStoragePoolLookupByName(vol->conn, vol->pool);
}

static int
3984 3985
testConnectNumOfStoragePools(virConnectPtr conn)
{
3986
    testDriverPtr privconn = conn->privateData;
3987 3988
    int numActive = 0;
    size_t i;
C
Cole Robinson 已提交
3989

3990
    testDriverLock(privconn);
3991
    for (i = 0; i < privconn->pools.count; i++)
C
Cole Robinson 已提交
3992 3993
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numActive++;
3994
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3995 3996 3997 3998 3999

    return numActive;
}

static int
4000 4001
testConnectListStoragePools(virConnectPtr conn,
                            char **const names,
4002 4003
                            int nnames)
{
4004
    testDriverPtr privconn = conn->privateData;
4005 4006
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
4007

4008
    testDriverLock(privconn);
C
Cole Robinson 已提交
4009
    memset(names, 0, sizeof(*names)*nnames);
4010
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
4011
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4012
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
4013
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
4014
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
4015
            goto error;
4016 4017 4018 4019
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4020 4021 4022

    return n;

4023
 error:
4024
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
4025
        VIR_FREE(names[n]);
4026
    testDriverUnlock(privconn);
4027
    return -1;
C
Cole Robinson 已提交
4028 4029 4030
}

static int
4031 4032
testConnectNumOfDefinedStoragePools(virConnectPtr conn)
{
4033
    testDriverPtr privconn = conn->privateData;
4034 4035
    int numInactive = 0;
    size_t i;
C
Cole Robinson 已提交
4036

4037
    testDriverLock(privconn);
4038
    for (i = 0; i < privconn->pools.count; i++) {
4039
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4040 4041
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numInactive++;
4042 4043 4044
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4045 4046 4047 4048 4049

    return numInactive;
}

static int
4050 4051
testConnectListDefinedStoragePools(virConnectPtr conn,
                                   char **const names,
4052 4053
                                   int nnames)
{
4054
    testDriverPtr privconn = conn->privateData;
4055 4056
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
4057

4058
    testDriverLock(privconn);
C
Cole Robinson 已提交
4059
    memset(names, 0, sizeof(*names)*nnames);
4060
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
4061
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4062
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
4063
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
4064
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
4065
            goto error;
4066 4067 4068 4069
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4070 4071 4072

    return n;

4073
 error:
4074
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
4075
        VIR_FREE(names[n]);
4076
    testDriverUnlock(privconn);
4077
    return -1;
C
Cole Robinson 已提交
4078 4079
}

4080
static int
4081 4082 4083
testConnectListAllStoragePools(virConnectPtr conn,
                               virStoragePoolPtr **pools,
                               unsigned int flags)
4084
{
4085
    testDriverPtr privconn = conn->privateData;
4086 4087 4088 4089 4090
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

    testDriverLock(privconn);
4091 4092
    ret = virStoragePoolObjListExport(conn, privconn->pools, pools,
                                      NULL, flags);
4093 4094 4095 4096
    testDriverUnlock(privconn);

    return ret;
}
C
Cole Robinson 已提交
4097

4098 4099
static int testStoragePoolIsActive(virStoragePoolPtr pool)
{
4100
    testDriverPtr privconn = pool->conn->privateData;
4101 4102 4103 4104 4105 4106 4107
    virStoragePoolObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virStoragePoolObjFindByUUID(&privconn->pools, pool->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
4108
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4109 4110 4111 4112
        goto cleanup;
    }
    ret = virStoragePoolObjIsActive(obj);

4113
 cleanup:
4114 4115 4116 4117 4118 4119 4120
    if (obj)
        virStoragePoolObjUnlock(obj);
    return ret;
}

static int testStoragePoolIsPersistent(virStoragePoolPtr pool)
{
4121
    testDriverPtr privconn = pool->conn->privateData;
4122 4123 4124 4125 4126 4127 4128
    virStoragePoolObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virStoragePoolObjFindByUUID(&privconn->pools, pool->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
4129
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4130 4131 4132 4133
        goto cleanup;
    }
    ret = obj->configFile ? 1 : 0;

4134
 cleanup:
4135 4136 4137 4138 4139 4140 4141
    if (obj)
        virStoragePoolObjUnlock(obj);
    return ret;
}



C
Cole Robinson 已提交
4142
static int
4143 4144
testStoragePoolCreate(virStoragePoolPtr pool,
                      unsigned int flags)
E
Eric Blake 已提交
4145
{
4146
    testDriverPtr privconn = pool->conn->privateData;
4147
    virStoragePoolObjPtr privpool;
4148
    int ret = -1;
4149

E
Eric Blake 已提交
4150 4151
    virCheckFlags(0, -1);

4152
    testDriverLock(privconn);
4153 4154
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4155
    testDriverUnlock(privconn);
4156 4157

    if (privpool == NULL) {
4158
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4159
        goto cleanup;
4160 4161
    }

4162
    if (virStoragePoolObjIsActive(privpool)) {
4163 4164
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4165 4166
        goto cleanup;
    }
C
Cole Robinson 已提交
4167 4168

    privpool->active = 1;
4169
    ret = 0;
C
Cole Robinson 已提交
4170

4171
 cleanup:
4172 4173
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4174
    return ret;
C
Cole Robinson 已提交
4175 4176 4177
}

static char *
4178 4179 4180 4181
testConnectFindStoragePoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type,
                                  const char *srcSpec,
                                  unsigned int flags)
C
Cole Robinson 已提交
4182
{
4183 4184 4185 4186
    virStoragePoolSourcePtr source = NULL;
    int pool_type;
    char *ret = NULL;

E
Eric Blake 已提交
4187 4188
    virCheckFlags(0, NULL);

4189 4190
    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
4191 4192
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
4193 4194 4195 4196
        goto cleanup;
    }

    if (srcSpec) {
4197
        source = virStoragePoolDefParseSourceString(srcSpec, pool_type);
4198 4199 4200 4201 4202 4203 4204
        if (!source)
            goto cleanup;
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
4205
        ignore_value(VIR_STRDUP(ret, defaultPoolSourcesLogicalXML));
4206 4207 4208
        break;

    case VIR_STORAGE_POOL_NETFS:
4209
        if (!source || !source->hosts[0].name) {
4210 4211
            virReportError(VIR_ERR_INVALID_ARG,
                           "%s", _("hostname must be specified for netfs sources"));
4212 4213 4214
            goto cleanup;
        }

4215 4216
        ignore_value(virAsprintf(&ret, defaultPoolSourcesNetFSXML,
                                 source->hosts[0].name));
4217 4218 4219
        break;

    default:
4220 4221
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source discovery"), type);
4222 4223
    }

4224
 cleanup:
4225 4226
    virStoragePoolSourceFree(source);
    return ret;
C
Cole Robinson 已提交
4227 4228 4229 4230
}


static virStoragePoolPtr
4231 4232 4233
testStoragePoolCreateXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4234
{
4235
    testDriverPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4236
    virStoragePoolDefPtr def;
4237
    virStoragePoolObjPtr pool = NULL;
4238
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4239

E
Eric Blake 已提交
4240 4241
    virCheckFlags(0, NULL);

4242
    testDriverLock(privconn);
4243
    if (!(def = virStoragePoolDefParseString(xml)))
4244
        goto cleanup;
C
Cole Robinson 已提交
4245

4246 4247 4248 4249
    pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid);
    if (!pool)
        pool = virStoragePoolObjFindByName(&privconn->pools, def->name);
    if (pool) {
4250 4251
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("storage pool already exists"));
4252
        goto cleanup;
C
Cole Robinson 已提交
4253 4254
    }

4255
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4256
        goto cleanup;
4257
    def = NULL;
C
Cole Robinson 已提交
4258

4259
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4260
        virStoragePoolObjRemove(&privconn->pools, pool);
4261 4262
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4263 4264 4265
    }
    pool->active = 1;

4266 4267
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4268

4269
 cleanup:
4270
    virStoragePoolDefFree(def);
4271 4272 4273
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4274
    return ret;
C
Cole Robinson 已提交
4275 4276 4277
}

static virStoragePoolPtr
4278 4279 4280
testStoragePoolDefineXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4281
{
4282
    testDriverPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4283
    virStoragePoolDefPtr def;
4284
    virStoragePoolObjPtr pool = NULL;
4285
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4286

E
Eric Blake 已提交
4287 4288
    virCheckFlags(0, NULL);

4289
    testDriverLock(privconn);
4290
    if (!(def = virStoragePoolDefParseString(xml)))
4291
        goto cleanup;
C
Cole Robinson 已提交
4292 4293 4294 4295 4296

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

4297
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4298 4299
        goto cleanup;
    def = NULL;
C
Cole Robinson 已提交
4300

4301
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4302
        virStoragePoolObjRemove(&privconn->pools, pool);
4303 4304
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4305 4306
    }

4307 4308
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4309

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

static int
4319 4320
testStoragePoolUndefine(virStoragePoolPtr pool)
{
4321
    testDriverPtr privconn = pool->conn->privateData;
4322
    virStoragePoolObjPtr privpool;
4323
    int ret = -1;
4324

4325
    testDriverLock(privconn);
4326 4327 4328 4329
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
4330
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4331
        goto cleanup;
4332 4333
    }

4334
    if (virStoragePoolObjIsActive(privpool)) {
4335 4336
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4337 4338
        goto cleanup;
    }
C
Cole Robinson 已提交
4339 4340

    virStoragePoolObjRemove(&privconn->pools, privpool);
4341
    privpool = NULL;
4342
    ret = 0;
C
Cole Robinson 已提交
4343

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

static int
4352
testStoragePoolBuild(virStoragePoolPtr pool,
E
Eric Blake 已提交
4353 4354
                     unsigned int flags)
{
4355
    testDriverPtr privconn = pool->conn->privateData;
4356
    virStoragePoolObjPtr privpool;
4357
    int ret = -1;
4358

E
Eric Blake 已提交
4359 4360
    virCheckFlags(0, -1);

4361
    testDriverLock(privconn);
4362 4363
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4364
    testDriverUnlock(privconn);
4365 4366

    if (privpool == NULL) {
4367
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4368
        goto cleanup;
4369 4370
    }

4371
    if (virStoragePoolObjIsActive(privpool)) {
4372 4373
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4374 4375
        goto cleanup;
    }
4376
    ret = 0;
C
Cole Robinson 已提交
4377

4378
 cleanup:
4379 4380
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4381
    return ret;
C
Cole Robinson 已提交
4382 4383 4384 4385
}


static int
4386 4387
testStoragePoolDestroy(virStoragePoolPtr pool)
{
4388
    testDriverPtr privconn = pool->conn->privateData;
4389
    virStoragePoolObjPtr privpool;
4390
    int ret = -1;
4391

4392
    testDriverLock(privconn);
4393 4394 4395 4396
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
4397
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4398
        goto cleanup;
4399 4400 4401
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4402 4403
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4404
        goto cleanup;
4405
    }
C
Cole Robinson 已提交
4406 4407 4408

    privpool->active = 0;

4409
    if (privpool->configFile == NULL) {
C
Cole Robinson 已提交
4410
        virStoragePoolObjRemove(&privconn->pools, privpool);
4411 4412
        privpool = NULL;
    }
4413
    ret = 0;
C
Cole Robinson 已提交
4414

4415
 cleanup:
4416 4417 4418
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
4419
    return ret;
C
Cole Robinson 已提交
4420 4421 4422 4423
}


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

E
Eric Blake 已提交
4431 4432
    virCheckFlags(0, -1);

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

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

    if (virStoragePoolObjIsActive(privpool)) {
4444 4445
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4446
        goto cleanup;
4447 4448
    }

4449
    ret = 0;
C
Cole Robinson 已提交
4450

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


static int
4459
testStoragePoolRefresh(virStoragePoolPtr pool,
E
Eric Blake 已提交
4460 4461
                       unsigned int flags)
{
4462
    testDriverPtr privconn = pool->conn->privateData;
4463
    virStoragePoolObjPtr privpool;
4464
    int ret = -1;
4465

E
Eric Blake 已提交
4466 4467
    virCheckFlags(0, -1);

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

    if (privpool == NULL) {
4474
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4475
        goto cleanup;
4476 4477 4478
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4479 4480
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4481
        goto cleanup;
4482
    }
4483
    ret = 0;
C
Cole Robinson 已提交
4484

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


static int
4493
testStoragePoolGetInfo(virStoragePoolPtr pool,
4494 4495
                       virStoragePoolInfoPtr info)
{
4496
    testDriverPtr privconn = pool->conn->privateData;
4497
    virStoragePoolObjPtr privpool;
4498
    int ret = -1;
4499

4500
    testDriverLock(privconn);
4501 4502
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4503
    testDriverUnlock(privconn);
4504 4505

    if (privpool == NULL) {
4506
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4507
        goto cleanup;
4508
    }
C
Cole Robinson 已提交
4509 4510 4511 4512 4513 4514 4515 4516 4517

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

4520
 cleanup:
4521 4522
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4523
    return ret;
C
Cole Robinson 已提交
4524 4525 4526
}

static char *
4527
testStoragePoolGetXMLDesc(virStoragePoolPtr pool,
E
Eric Blake 已提交
4528 4529
                          unsigned int flags)
{
4530
    testDriverPtr privconn = pool->conn->privateData;
4531
    virStoragePoolObjPtr privpool;
4532
    char *ret = NULL;
4533

E
Eric Blake 已提交
4534 4535
    virCheckFlags(0, NULL);

4536
    testDriverLock(privconn);
4537 4538
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4539
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4540

4541
    if (privpool == NULL) {
4542
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4543
        goto cleanup;
4544 4545
    }

4546
    ret = virStoragePoolDefFormat(privpool->def);
4547

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

static int
4555
testStoragePoolGetAutostart(virStoragePoolPtr pool,
4556 4557
                            int *autostart)
{
4558
    testDriverPtr privconn = pool->conn->privateData;
4559
    virStoragePoolObjPtr privpool;
4560
    int ret = -1;
4561

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

    if (privpool == NULL) {
4568
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4569
        goto cleanup;
4570
    }
C
Cole Robinson 已提交
4571 4572 4573 4574 4575 4576

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

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

static int
4586
testStoragePoolSetAutostart(virStoragePoolPtr pool,
4587 4588
                            int autostart)
{
4589
    testDriverPtr privconn = pool->conn->privateData;
4590
    virStoragePoolObjPtr privpool;
4591
    int ret = -1;
4592

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

    if (privpool == NULL) {
4599
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4600
        goto cleanup;
4601
    }
C
Cole Robinson 已提交
4602 4603

    if (!privpool->configFile) {
4604 4605
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("pool has no config file"));
4606
        goto cleanup;
C
Cole Robinson 已提交
4607 4608 4609 4610
    }

    autostart = (autostart != 0);
    privpool->autostart = autostart;
4611 4612
    ret = 0;

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


static int
4621 4622
testStoragePoolNumOfVolumes(virStoragePoolPtr pool)
{
4623
    testDriverPtr privconn = pool->conn->privateData;
4624
    virStoragePoolObjPtr privpool;
4625
    int ret = -1;
4626

4627
    testDriverLock(privconn);
4628 4629
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4630
    testDriverUnlock(privconn);
4631 4632

    if (privpool == NULL) {
4633
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4634
        goto cleanup;
4635 4636 4637
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4638 4639
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4640
        goto cleanup;
4641
    }
C
Cole Robinson 已提交
4642

4643 4644
    ret = privpool->volumes.count;

4645
 cleanup:
4646 4647
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4648
    return ret;
C
Cole Robinson 已提交
4649 4650 4651
}

static int
4652
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4653
                           char **const names,
4654 4655
                           int maxnames)
{
4656
    testDriverPtr privconn = pool->conn->privateData;
4657
    virStoragePoolObjPtr privpool;
4658 4659
    size_t i = 0;
    int n = 0;
C
Cole Robinson 已提交
4660

4661
    memset(names, 0, maxnames * sizeof(*names));
4662 4663

    testDriverLock(privconn);
4664 4665
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4666
    testDriverUnlock(privconn);
4667 4668

    if (privpool == NULL) {
4669
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4670
        goto cleanup;
4671 4672 4673 4674
    }


    if (!virStoragePoolObjIsActive(privpool)) {
4675 4676
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4677
        goto cleanup;
4678 4679
    }

4680
    for (i = 0; i < privpool->volumes.count && n < maxnames; i++) {
4681
        if (VIR_STRDUP(names[n++], privpool->volumes.objs[i]->name) < 0)
C
Cole Robinson 已提交
4682 4683 4684
            goto cleanup;
    }

4685
    virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4686 4687 4688
    return n;

 cleanup:
4689
    for (n = 0; n < maxnames; n++)
C
Cole Robinson 已提交
4690 4691
        VIR_FREE(names[i]);

4692
    memset(names, 0, maxnames * sizeof(*names));
4693 4694
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4695 4696 4697
    return -1;
}

4698 4699 4700
static int
testStoragePoolListAllVolumes(virStoragePoolPtr obj,
                              virStorageVolPtr **vols,
4701 4702
                              unsigned int flags)
{
4703
    testDriverPtr privconn = obj->conn->privateData;
4704
    virStoragePoolObjPtr pool;
4705
    size_t i;
4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734
    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;
    }

4735
    if (VIR_ALLOC_N(tmp_vols, pool->volumes.count + 1) < 0)
4736 4737
         goto cleanup;

4738
    for (i = 0; i < pool->volumes.count; i++) {
4739 4740
        if (!(vol = virGetStorageVol(obj->conn, pool->def->name,
                                     pool->volumes.objs[i]->name,
4741 4742
                                     pool->volumes.objs[i]->key,
                                     NULL, NULL)))
4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756
            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]);
        }
4757
        VIR_FREE(tmp_vols);
4758 4759 4760 4761 4762 4763 4764
    }

    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
C
Cole Robinson 已提交
4765 4766

static virStorageVolPtr
4767
testStorageVolLookupByName(virStoragePoolPtr pool,
4768 4769
                           const char *name ATTRIBUTE_UNUSED)
{
4770
    testDriverPtr privconn = pool->conn->privateData;
4771 4772
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
4773
    virStorageVolPtr ret = NULL;
4774

4775
    testDriverLock(privconn);
4776 4777
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4778
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4779

4780
    if (privpool == NULL) {
4781
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4782
        goto cleanup;
4783 4784 4785 4786
    }


    if (!virStoragePoolObjIsActive(privpool)) {
4787 4788
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4789
        goto cleanup;
4790 4791 4792 4793 4794
    }

    privvol = virStorageVolDefFindByName(privpool, name);

    if (!privvol) {
4795 4796
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"), name);
4797
        goto cleanup;
C
Cole Robinson 已提交
4798 4799
    }

4800
    ret = virGetStorageVol(pool->conn, privpool->def->name,
4801 4802
                           privvol->name, privvol->key,
                           NULL, NULL);
4803

4804
 cleanup:
4805 4806
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4807
    return ret;
C
Cole Robinson 已提交
4808 4809 4810 4811
}


static virStorageVolPtr
4812
testStorageVolLookupByKey(virConnectPtr conn,
4813 4814
                          const char *key)
{
4815
    testDriverPtr privconn = conn->privateData;
4816
    size_t i;
4817
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4818

4819
    testDriverLock(privconn);
4820
    for (i = 0; i < privconn->pools.count; i++) {
4821
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4822
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4823
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4824 4825
                virStorageVolDefFindByKey(privconn->pools.objs[i], key);

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

4840
    if (!ret)
4841 4842
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching key '%s'"), key);
4843 4844

    return ret;
C
Cole Robinson 已提交
4845 4846 4847
}

static virStorageVolPtr
4848
testStorageVolLookupByPath(virConnectPtr conn,
4849 4850
                           const char *path)
{
4851
    testDriverPtr privconn = conn->privateData;
4852
    size_t i;
4853
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4854

4855
    testDriverLock(privconn);
4856
    for (i = 0; i < privconn->pools.count; i++) {
4857
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4858
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4859
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4860 4861
                virStorageVolDefFindByPath(privconn->pools.objs[i], path);

4862 4863 4864 4865
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
4866 4867
                                       privvol->key,
                                       NULL, NULL);
4868
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
4869 4870
                break;
            }
C
Cole Robinson 已提交
4871
        }
4872
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4873
    }
4874
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4875

4876
    if (!ret)
4877 4878
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching path '%s'"), path);
4879 4880

    return ret;
C
Cole Robinson 已提交
4881 4882 4883
}

static virStorageVolPtr
4884 4885 4886
testStorageVolCreateXML(virStoragePoolPtr pool,
                        const char *xmldesc,
                        unsigned int flags)
E
Eric Blake 已提交
4887
{
4888
    testDriverPtr privconn = pool->conn->privateData;
4889
    virStoragePoolObjPtr privpool;
4890 4891
    virStorageVolDefPtr privvol = NULL;
    virStorageVolPtr ret = NULL;
4892

E
Eric Blake 已提交
4893 4894
    virCheckFlags(0, NULL);

4895
    testDriverLock(privconn);
4896 4897
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4898
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4899

4900
    if (privpool == NULL) {
4901
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4902
        goto cleanup;
4903 4904 4905
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4906 4907
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4908
        goto cleanup;
4909
    }
C
Cole Robinson 已提交
4910

4911
    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
4912
    if (privvol == NULL)
4913
        goto cleanup;
4914 4915

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
4916 4917
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
4918
        goto cleanup;
C
Cole Robinson 已提交
4919 4920 4921
    }

    /* Make sure enough space */
4922
    if ((privpool->def->allocation + privvol->target.allocation) >
C
Cole Robinson 已提交
4923
         privpool->def->capacity) {
4924 4925 4926
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
4927
        goto cleanup;
C
Cole Robinson 已提交
4928 4929
    }

4930 4931
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
4932
                    privvol->name) == -1)
4933
        goto cleanup;
C
Cole Robinson 已提交
4934

4935 4936 4937
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
        VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
                                privpool->volumes.count, privvol) < 0)
4938
        goto cleanup;
C
Cole Robinson 已提交
4939

4940
    privpool->def->allocation += privvol->target.allocation;
C
Cole Robinson 已提交
4941 4942 4943
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

4944
    ret = virGetStorageVol(pool->conn, privpool->def->name,
4945 4946
                           privvol->name, privvol->key,
                           NULL, NULL);
4947
    privvol = NULL;
4948

4949
 cleanup:
4950
    virStorageVolDefFree(privvol);
4951 4952
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4953
    return ret;
C
Cole Robinson 已提交
4954 4955
}

4956
static virStorageVolPtr
4957 4958 4959 4960
testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
                            const char *xmldesc,
                            virStorageVolPtr clonevol,
                            unsigned int flags)
E
Eric Blake 已提交
4961
{
4962
    testDriverPtr privconn = pool->conn->privateData;
4963 4964 4965 4966
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol = NULL, origvol = NULL;
    virStorageVolPtr ret = NULL;

E
Eric Blake 已提交
4967 4968
    virCheckFlags(0, NULL);

4969 4970 4971 4972 4973 4974
    testDriverLock(privconn);
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
    testDriverUnlock(privconn);

    if (privpool == NULL) {
4975
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4976 4977 4978 4979
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4980 4981
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4982 4983 4984
        goto cleanup;
    }

4985
    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
4986 4987 4988 4989
    if (privvol == NULL)
        goto cleanup;

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
4990 4991
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
4992 4993 4994 4995 4996
        goto cleanup;
    }

    origvol = virStorageVolDefFindByName(privpool, clonevol->name);
    if (!origvol) {
4997 4998 4999
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       clonevol->name);
5000 5001 5002 5003
        goto cleanup;
    }

    /* Make sure enough space */
5004
    if ((privpool->def->allocation + privvol->target.allocation) >
5005
         privpool->def->capacity) {
5006 5007 5008
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
5009 5010 5011 5012 5013
        goto cleanup;
    }
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

5014 5015
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
5016
                    privvol->name) == -1)
5017 5018
        goto cleanup;

5019 5020 5021
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
        VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
                                privpool->volumes.count, privvol) < 0)
5022 5023
        goto cleanup;

5024
    privpool->def->allocation += privvol->target.allocation;
5025 5026 5027 5028
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    ret = virGetStorageVol(pool->conn, privpool->def->name,
5029 5030
                           privvol->name, privvol->key,
                           NULL, NULL);
5031 5032
    privvol = NULL;

5033
 cleanup:
5034 5035 5036 5037 5038 5039
    virStorageVolDefFree(privvol);
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    return ret;
}

C
Cole Robinson 已提交
5040
static int
5041 5042
testStorageVolDelete(virStorageVolPtr vol,
                     unsigned int flags)
E
Eric Blake 已提交
5043
{
5044
    testDriverPtr privconn = vol->conn->privateData;
5045 5046
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5047
    size_t i;
5048
    int ret = -1;
C
Cole Robinson 已提交
5049

E
Eric Blake 已提交
5050 5051
    virCheckFlags(0, -1);

5052
    testDriverLock(privconn);
5053 5054
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5055
    testDriverUnlock(privconn);
5056 5057

    if (privpool == NULL) {
5058
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5059
        goto cleanup;
5060 5061 5062 5063 5064 5065
    }


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

    if (privvol == NULL) {
5066 5067 5068
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5069
        goto cleanup;
5070 5071 5072
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5073 5074
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5075
        goto cleanup;
5076 5077 5078
    }


5079
    privpool->def->allocation -= privvol->target.allocation;
C
Cole Robinson 已提交
5080 5081 5082
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

5083
    for (i = 0; i < privpool->volumes.count; i++) {
C
Cole Robinson 已提交
5084 5085 5086
        if (privpool->volumes.objs[i] == privvol) {
            virStorageVolDefFree(privvol);

5087
            VIR_DELETE_ELEMENT(privpool->volumes.objs, i, privpool->volumes.count);
C
Cole Robinson 已提交
5088 5089 5090
            break;
        }
    }
5091
    ret = 0;
C
Cole Robinson 已提交
5092

5093
 cleanup:
5094 5095
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5096
    return ret;
C
Cole Robinson 已提交
5097 5098 5099
}


5100 5101
static int testStorageVolumeTypeForPool(int pooltype)
{
C
Cole Robinson 已提交
5102

5103
    switch (pooltype) {
C
Cole Robinson 已提交
5104 5105 5106 5107 5108 5109 5110 5111 5112 5113
        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
5114
testStorageVolGetInfo(virStorageVolPtr vol,
5115 5116
                      virStorageVolInfoPtr info)
{
5117
    testDriverPtr privconn = vol->conn->privateData;
5118 5119
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5120
    int ret = -1;
5121

5122
    testDriverLock(privconn);
5123 5124
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5125
    testDriverUnlock(privconn);
5126 5127

    if (privpool == NULL) {
5128
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5129
        goto cleanup;
5130 5131 5132 5133 5134
    }

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

    if (privvol == NULL) {
5135 5136 5137
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5138
        goto cleanup;
5139 5140 5141
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5142 5143
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5144
        goto cleanup;
5145
    }
C
Cole Robinson 已提交
5146 5147 5148

    memset(info, 0, sizeof(*info));
    info->type = testStorageVolumeTypeForPool(privpool->def->type);
5149 5150
    info->capacity = privvol->target.capacity;
    info->allocation = privvol->target.allocation;
5151
    ret = 0;
C
Cole Robinson 已提交
5152

5153
 cleanup:
5154 5155
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5156
    return ret;
C
Cole Robinson 已提交
5157 5158 5159
}

static char *
5160 5161
testStorageVolGetXMLDesc(virStorageVolPtr vol,
                         unsigned int flags)
E
Eric Blake 已提交
5162
{
5163
    testDriverPtr privconn = vol->conn->privateData;
5164 5165
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5166
    char *ret = NULL;
5167

E
Eric Blake 已提交
5168 5169
    virCheckFlags(0, NULL);

5170
    testDriverLock(privconn);
5171 5172
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5173
    testDriverUnlock(privconn);
5174 5175

    if (privpool == NULL) {
5176
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5177
        goto cleanup;
5178 5179 5180 5181 5182
    }

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

    if (privvol == NULL) {
5183 5184 5185
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5186
        goto cleanup;
5187
    }
C
Cole Robinson 已提交
5188

5189
    if (!virStoragePoolObjIsActive(privpool)) {
5190 5191
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5192
        goto cleanup;
5193 5194
    }

5195
    ret = virStorageVolDefFormat(privpool->def, privvol);
5196

5197
 cleanup:
5198 5199
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5200
    return ret;
C
Cole Robinson 已提交
5201 5202 5203
}

static char *
5204 5205
testStorageVolGetPath(virStorageVolPtr vol)
{
5206
    testDriverPtr privconn = vol->conn->privateData;
5207 5208
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5209
    char *ret = NULL;
5210

5211
    testDriverLock(privconn);
5212 5213
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5214
    testDriverUnlock(privconn);
5215 5216

    if (privpool == NULL) {
5217
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5218
        goto cleanup;
5219 5220 5221 5222 5223
    }

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

    if (privvol == NULL) {
5224 5225 5226
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5227
        goto cleanup;
5228 5229 5230
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5231 5232
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5233
        goto cleanup;
5234 5235
    }

5236
    ignore_value(VIR_STRDUP(ret, privvol->target.path));
5237

5238
 cleanup:
5239 5240
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
5241 5242 5243
    return ret;
}

5244

5245
/* Node device implementations */
5246

5247 5248 5249
static int
testNodeNumOfDevices(virConnectPtr conn,
                     const char *cap,
E
Eric Blake 已提交
5250
                     unsigned int flags)
5251
{
5252
    testDriverPtr driver = conn->privateData;
5253
    int ndevs = 0;
5254
    size_t i;
5255

E
Eric Blake 已提交
5256 5257
    virCheckFlags(0, -1);

5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272
    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 已提交
5273
                    unsigned int flags)
5274
{
5275
    testDriverPtr driver = conn->privateData;
5276
    int ndevs = 0;
5277
    size_t i;
5278

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

5281 5282 5283 5284 5285
    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)) {
5286
            if (VIR_STRDUP(names[ndevs++], driver->devs.objs[i]->def->name) < 0) {
5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307
                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)
{
5308
    testDriverPtr driver = conn->privateData;
5309 5310 5311 5312 5313 5314 5315 5316
    virNodeDeviceObjPtr obj;
    virNodeDevicePtr ret = NULL;

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

    if (!obj) {
5317 5318 5319
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       name);
5320 5321 5322 5323 5324
        goto cleanup;
    }

    ret = virGetNodeDevice(conn, name);

5325
 cleanup:
5326 5327 5328 5329 5330 5331
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

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

E
Eric Blake 已提交
5339 5340
    virCheckFlags(0, NULL);

5341 5342 5343 5344 5345
    testDriverLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
    testDriverUnlock(driver);

    if (!obj) {
5346 5347 5348
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5349 5350 5351
        goto cleanup;
    }

5352
    ret = virNodeDeviceDefFormat(obj->def);
5353

5354
 cleanup:
5355 5356 5357 5358 5359 5360 5361 5362
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

static char *
testNodeDeviceGetParent(virNodeDevicePtr dev)
{
5363
    testDriverPtr driver = dev->conn->privateData;
5364 5365 5366 5367 5368 5369 5370 5371
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

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

    if (!obj) {
5372 5373 5374
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5375 5376 5377 5378
        goto cleanup;
    }

    if (obj->def->parent) {
5379
        ignore_value(VIR_STRDUP(ret, obj->def->parent));
5380
    } else {
5381 5382
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no parent for this device"));
5383 5384
    }

5385
 cleanup:
5386 5387 5388 5389 5390
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

5391

5392 5393 5394
static int
testNodeDeviceNumOfCaps(virNodeDevicePtr dev)
{
5395
    testDriverPtr driver = dev->conn->privateData;
5396 5397 5398 5399 5400 5401 5402 5403 5404 5405
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

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

    if (!obj) {
5406 5407 5408
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5409 5410 5411 5412 5413 5414 5415
        goto cleanup;
    }

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

5416
 cleanup:
5417 5418 5419 5420 5421 5422 5423 5424 5425
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}


static int
testNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
5426
    testDriverPtr driver = dev->conn->privateData;
5427 5428 5429 5430 5431 5432 5433 5434 5435 5436
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

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

    if (!obj) {
5437 5438 5439
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5440 5441 5442 5443
        goto cleanup;
    }

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

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

5460 5461 5462
static virNodeDevicePtr
testNodeDeviceCreateXML(virConnectPtr conn,
                        const char *xmlDesc,
E
Eric Blake 已提交
5463
                        unsigned int flags)
5464
{
5465
    testDriverPtr driver = conn->privateData;
5466 5467 5468 5469 5470 5471 5472
    virNodeDeviceDefPtr def = NULL;
    virNodeDeviceObjPtr obj = NULL;
    char *wwnn = NULL, *wwpn = NULL;
    int parent_host = -1;
    virNodeDevicePtr dev = NULL;
    virNodeDevCapsDefPtr caps;

E
Eric Blake 已提交
5473 5474
    virCheckFlags(0, NULL);

5475 5476
    testDriverLock(driver);

5477
    def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, NULL);
5478
    if (def == NULL)
5479 5480 5481
        goto cleanup;

    /* We run these next two simply for validation */
5482
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) == -1)
5483 5484
        goto cleanup;

5485
    if (virNodeDeviceGetParentHost(&driver->devs,
5486 5487 5488 5489 5490 5491 5492 5493 5494
                                   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);
5495
    if (VIR_STRDUP(def->name, wwpn) < 0)
5496 5497
        goto cleanup;

J
John Ferlan 已提交
5498 5499
    /* Fill in a random 'host' and 'unique_id' value,
     * since this would also come from the backend */
5500 5501
    caps = def->caps;
    while (caps) {
5502
        if (caps->data.type != VIR_NODE_DEV_CAP_SCSI_HOST)
5503 5504
            continue;

5505
        caps->data.scsi_host.host = virRandomBits(10);
J
John Ferlan 已提交
5506
        caps->data.scsi_host.unique_id = 2;
5507 5508 5509 5510
        caps = caps->next;
    }


5511
    if (!(obj = virNodeDeviceAssignDef(&driver->devs, def)))
5512 5513 5514 5515 5516
        goto cleanup;
    virNodeDeviceObjUnlock(obj);

    dev = virGetNodeDevice(conn, def->name);
    def = NULL;
5517
 cleanup:
5518
    testDriverUnlock(driver);
5519
    virNodeDeviceDefFree(def);
5520 5521 5522 5523 5524 5525 5526 5527 5528
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return dev;
}

static int
testNodeDeviceDestroy(virNodeDevicePtr dev)
{
    int ret = 0;
5529
    testDriverPtr driver = dev->conn->privateData;
5530 5531 5532 5533 5534 5535 5536 5537 5538
    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) {
5539 5540 5541
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5542 5543 5544
        goto out;
    }

5545
    if (virNodeDeviceGetWWNs(obj->def, &wwnn, &wwpn) == -1)
5546 5547
        goto out;

5548
    if (VIR_STRDUP(parent_name, obj->def->parent) < 0)
5549 5550 5551 5552 5553 5554 5555 5556 5557
        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 */
5558
    if (virNodeDeviceGetParentHost(&driver->devs,
5559 5560 5561 5562 5563 5564 5565 5566 5567 5568
                                   dev->name,
                                   parent_name,
                                   &parent_host) == -1) {
        obj = NULL;
        goto out;
    }

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

5569
 out:
5570 5571 5572 5573 5574 5575 5576 5577
    if (obj)
        virNodeDeviceObjUnlock(obj);
    VIR_FREE(parent_name);
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return ret;
}

5578 5579

/* Domain event implementations */
5580
static int
5581 5582 5583 5584
testConnectDomainEventRegister(virConnectPtr conn,
                               virConnectDomainEventCallback callback,
                               void *opaque,
                               virFreeCallback freecb)
5585
{
5586
    testDriverPtr driver = conn->privateData;
5587
    int ret = 0;
5588

5589
    if (virDomainEventStateRegister(conn, driver->eventState,
5590 5591
                                    callback, opaque, freecb) < 0)
        ret = -1;
5592 5593 5594 5595

    return ret;
}

5596

5597
static int
5598 5599
testConnectDomainEventDeregister(virConnectPtr conn,
                                 virConnectDomainEventCallback callback)
5600
{
5601
    testDriverPtr driver = conn->privateData;
5602
    int ret = 0;
5603

5604
    if (virDomainEventStateDeregister(conn, driver->eventState,
5605 5606
                                      callback) < 0)
        ret = -1;
5607 5608 5609 5610

    return ret;
}

5611 5612

static int
5613 5614 5615 5616 5617 5618
testConnectDomainEventRegisterAny(virConnectPtr conn,
                                  virDomainPtr dom,
                                  int eventID,
                                  virConnectDomainEventGenericCallback callback,
                                  void *opaque,
                                  virFreeCallback freecb)
5619
{
5620
    testDriverPtr driver = conn->privateData;
5621 5622
    int ret;

5623
    if (virDomainEventStateRegisterID(conn, driver->eventState,
5624 5625
                                      dom, eventID,
                                      callback, opaque, freecb, &ret) < 0)
5626
        ret = -1;
5627 5628 5629 5630 5631

    return ret;
}

static int
5632 5633
testConnectDomainEventDeregisterAny(virConnectPtr conn,
                                    int callbackID)
5634
{
5635
    testDriverPtr driver = conn->privateData;
5636
    int ret = 0;
5637

5638
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5639 5640
                                        callbackID) < 0)
        ret = -1;
5641 5642 5643 5644 5645

    return ret;
}


5646 5647 5648 5649 5650 5651 5652 5653
static int
testConnectNetworkEventRegisterAny(virConnectPtr conn,
                                   virNetworkPtr net,
                                   int eventID,
                                   virConnectNetworkEventGenericCallback callback,
                                   void *opaque,
                                   virFreeCallback freecb)
{
5654
    testDriverPtr driver = conn->privateData;
5655 5656
    int ret;

5657
    if (virNetworkEventStateRegisterID(conn, driver->eventState,
5658
                                       net, eventID, callback,
5659 5660 5661 5662 5663 5664 5665 5666 5667 5668
                                       opaque, freecb, &ret) < 0)
        ret = -1;

    return ret;
}

static int
testConnectNetworkEventDeregisterAny(virConnectPtr conn,
                                     int callbackID)
{
5669
    testDriverPtr driver = conn->privateData;
5670
    int ret = 0;
5671

5672
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5673 5674
                                        callbackID) < 0)
        ret = -1;
5675 5676 5677 5678

    return ret;
}

5679 5680 5681
static int testConnectListAllDomains(virConnectPtr conn,
                                     virDomainPtr **domains,
                                     unsigned int flags)
5682
{
5683
    testDriverPtr privconn = conn->privateData;
5684

O
Osier Yang 已提交
5685
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
5686

5687 5688
    return virDomainObjListExport(privconn->domains, conn, domains,
                                  NULL, flags);
5689 5690
}

5691
static int
P
Peter Krempa 已提交
5692
testNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,
5693 5694 5695 5696 5697 5698 5699
                  unsigned char **cpumap,
                  unsigned int *online,
                  unsigned int flags)
{
    virCheckFlags(0, -1);

    if (cpumap) {
5700
        if (VIR_ALLOC_N(*cpumap, 1) < 0)
P
Peter Krempa 已提交
5701
            return -1;
5702 5703 5704 5705 5706 5707
        *cpumap[0] = 0x15;
    }

    if (online)
        *online = 3;

P
Peter Krempa 已提交
5708
    return  8;
5709 5710
}

5711 5712 5713 5714 5715 5716 5717 5718 5719 5720
static char *
testDomainScreenshot(virDomainPtr dom ATTRIBUTE_UNUSED,
                     virStreamPtr st,
                     unsigned int screen ATTRIBUTE_UNUSED,
                     unsigned int flags)
{
    char *ret = NULL;

    virCheckFlags(0, NULL);

5721
    if (VIR_STRDUP(ret, "image/png") < 0)
5722 5723
        return NULL;

5724
    if (virFDStreamOpenFile(st, PKGDATADIR "/libvirtLogo.png", 0, 0, O_RDONLY) < 0)
5725 5726 5727 5728 5729
        VIR_FREE(ret);

    return ret;
}

5730 5731 5732 5733 5734 5735 5736 5737 5738
static int
testConnectGetCPUModelNames(virConnectPtr conn ATTRIBUTE_UNUSED,
                            const char *arch,
                            char ***models,
                            unsigned int flags)
{
    virCheckFlags(0, -1);
    return cpuGetModels(arch, models);
}
5739

C
Cole Robinson 已提交
5740 5741 5742
static int
testDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
5743
    testDriverPtr privconn = dom->conn->privateData;
C
Cole Robinson 已提交
5744
    virDomainObjPtr vm = NULL;
5745
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
5746 5747 5748 5749 5750 5751
    int ret = -1;

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

5752 5753
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767

    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);
5768
    event = virDomainEventLifecycleNewFromObj(vm,
C
Cole Robinson 已提交
5769 5770 5771 5772 5773
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
    vm->hasManagedSave = true;

    ret = 0;
5774
 cleanup:
5775
    virDomainObjEndAPI(&vm);
5776
    testObjectEventQueue(privconn, event);
C
Cole Robinson 已提交
5777 5778 5779 5780 5781 5782 5783 5784 5785

    return ret;
}


static int
testDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm;
5786
    int ret;
C
Cole Robinson 已提交
5787 5788 5789

    virCheckFlags(0, -1);

5790 5791
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5792 5793

    ret = vm->hasManagedSave;
5794

5795
    virDomainObjEndAPI(&vm);
C
Cole Robinson 已提交
5796 5797 5798 5799 5800 5801 5802 5803 5804 5805
    return ret;
}

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

    virCheckFlags(0, -1);

5806 5807
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5808 5809

    vm->hasManagedSave = false;
5810

5811
    virDomainObjEndAPI(&vm);
5812
    return 0;
C
Cole Robinson 已提交
5813 5814 5815
}


5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849
/*
 * 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;
5850
    int n;
5851 5852 5853 5854 5855

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5856
        return -1;
5857 5858 5859

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

5860
    virDomainObjEndAPI(&vm);
5861 5862 5863 5864 5865 5866 5867 5868 5869 5870
    return n;
}

static int
testDomainSnapshotListNames(virDomainPtr domain,
                            char **names,
                            int nameslen,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
5871
    int n;
5872 5873 5874 5875 5876

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5877
        return -1;
5878 5879 5880 5881

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

5882
    virDomainObjEndAPI(&vm);
5883 5884 5885 5886 5887 5888 5889 5890 5891
    return n;
}

static int
testDomainListAllSnapshots(virDomainPtr domain,
                           virDomainSnapshotPtr **snaps,
                           unsigned int flags)
{
    virDomainObjPtr vm = NULL;
5892
    int n;
5893 5894 5895 5896 5897

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5898
        return -1;
5899 5900 5901

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

5902
    virDomainObjEndAPI(&vm);
5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919
    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)))
5920
        return -1;
5921 5922 5923 5924 5925 5926 5927

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

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

5928
 cleanup:
5929
    virDomainObjEndAPI(&vm);
5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944
    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)))
5945
        return -1;
5946 5947 5948 5949 5950 5951

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

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

5952
 cleanup:
5953
    virDomainObjEndAPI(&vm);
5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969
    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)))
5970
        return -1;
5971 5972 5973 5974 5975 5976 5977

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

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

5978
 cleanup:
5979
    virDomainObjEndAPI(&vm);
5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994
    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)))
5995
        return NULL;
5996 5997 5998 5999 6000 6001

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

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

6002
 cleanup:
6003
    virDomainObjEndAPI(&vm);
6004 6005 6006 6007 6008 6009 6010 6011
    return snapshot;
}

static int
testDomainHasCurrentSnapshot(virDomainPtr domain,
                             unsigned int flags)
{
    virDomainObjPtr vm;
6012
    int ret;
6013 6014 6015 6016

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6017
        return -1;
6018 6019 6020

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

6021
    virDomainObjEndAPI(&vm);
6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035
    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)))
6036
        return NULL;
6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049

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

6050
 cleanup:
6051
    virDomainObjEndAPI(&vm);
6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064
    return parent;
}

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

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
6065
        return NULL;
6066 6067 6068 6069 6070 6071 6072 6073 6074

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

6075
 cleanup:
6076
    virDomainObjEndAPI(&vm);
6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091
    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];

    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6092
        return NULL;
6093 6094 6095 6096 6097 6098

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

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

6099 6100 6101
    xml = virDomainSnapshotDefFormat(uuidstr, snap->def,
                                     virDomainDefFormatConvertXMLFlags(flags),
                                     0);
6102

6103
 cleanup:
6104
    virDomainObjEndAPI(&vm);
6105 6106 6107 6108 6109 6110 6111 6112
    return xml;
}

static int
testDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6113
    int ret;
6114 6115 6116 6117

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6118
        return -1;
6119 6120 6121 6122

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

6123
    virDomainObjEndAPI(&vm);
6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137
    return ret;
}


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

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6138
        return -1;
6139

C
Cole Robinson 已提交
6140
    if (!testSnapObjFromSnapshot(vm, snapshot))
6141 6142 6143 6144
        goto cleanup;

    ret = 1;

6145
 cleanup:
6146
    virDomainObjEndAPI(&vm);
6147 6148 6149
    return ret;
}

6150 6151 6152 6153 6154 6155
static int
testDomainSnapshotAlignDisks(virDomainObjPtr vm,
                             virDomainSnapshotDefPtr def,
                             unsigned int flags)
{
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
E
Eric Blake 已提交
6156
    bool align_match = true;
6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184

    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)
{
6185
    testDriverPtr privconn = domain->conn->privateData;
6186 6187 6188 6189
    virDomainObjPtr vm = NULL;
    virDomainSnapshotDefPtr def = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr snapshot = NULL;
6190
    virObjectEventPtr event = NULL;
6191
    char *xml = NULL;
6192 6193
    bool update_current = true;
    bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
6194 6195 6196 6197 6198 6199 6200 6201
    unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;

    /*
     * DISK_ONLY: Not implemented yet
     * REUSE_EXT: Not implemented yet
     *
     * NO_METADATA: Explicitly not implemented
     *
6202
     * REDEFINE + CURRENT: Implemented
6203 6204 6205 6206 6207 6208
     * HALT: Implemented
     * QUIESCE: Nothing to do
     * ATOMIC: Nothing to do
     * LIVE: Nothing to do
     */
    virCheckFlags(
6209 6210
        VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
        VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
6211 6212 6213 6214 6215
        VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
        VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
        VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
        VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, NULL);

6216 6217 6218 6219 6220
    if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)))
        update_current = false;
    if (redefine)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;

6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235
    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;

6236
    if (redefine) {
C
Cole Robinson 已提交
6237 6238
        if (virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
                                          &update_current, flags) < 0)
6239 6240 6241 6242 6243 6244 6245
            goto cleanup;
    } else {
        if (!(def->dom = virDomainDefCopy(vm->def,
                                          privconn->caps,
                                          privconn->xmlopt,
                                          true)))
            goto cleanup;
6246

6247
        if (testDomainSnapshotAlignDisks(vm, def, flags) < 0)
6248 6249 6250
            goto cleanup;
    }

6251 6252 6253 6254
    if (!snap) {
        if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
            goto cleanup;
        def = NULL;
6255 6256
    }

6257 6258 6259 6260 6261 6262 6263 6264 6265 6266
    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);
6267
            event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
6268 6269 6270
                                    VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
        }
    }
6271 6272

    snapshot = virGetDomainSnapshot(domain, snap->def->name);
6273
 cleanup:
6274 6275 6276 6277
    VIR_FREE(xml);
    if (vm) {
        if (snapshot) {
            virDomainSnapshotObjPtr other;
6278 6279
            if (update_current)
                vm->current_snapshot = snap;
6280 6281 6282 6283 6284 6285 6286
            other = virDomainSnapshotFindByName(vm->snapshots,
                                                snap->def->parent);
            snap->parent = other;
            other->nchildren++;
            snap->sibling = other->first_child;
            other->first_child = snap;
        }
6287
        virDomainObjEndAPI(&vm);
6288
    }
6289
    testObjectEventQueue(privconn, event);
6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331
    virDomainSnapshotDefFree(def);
    return snapshot;
}


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

static void
testDomainSnapshotDiscardAll(void *payload,
                          const void *name ATTRIBUTE_UNUSED,
                          void *data)
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapRemoveDataPtr curr = data;

    if (snap->def->current)
        curr->current = true;
    virDomainSnapshotObjListRemove(curr->vm->snapshots, snap);
}

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

static void
testDomainSnapshotReparentChildren(void *payload,
                                   const void *name ATTRIBUTE_UNUSED,
                                   void *data)
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapReparentDataPtr rep = data;

6332
    if (rep->err < 0)
6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374
        return;

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

    if (!snap->sibling)
        rep->last = snap;
}

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) {
6375
            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)
6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418
                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;
6419
 cleanup:
6420
    virDomainObjEndAPI(&vm);
6421 6422 6423 6424 6425 6426 6427
    return ret;
}

static int
testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                           unsigned int flags)
{
6428
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6429 6430
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
6431 6432
    virObjectEventPtr event = NULL;
    virObjectEventPtr event2 = NULL;
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 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523
    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);
6524
                event = virDomainEventLifecycleNewFromObj(vm,
6525 6526
                            VIR_DOMAIN_EVENT_STOPPED,
                            VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
6527
                testObjectEventQueue(privconn, event);
6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538
                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. */
6539
                event = virDomainEventLifecycleNewFromObj(vm,
6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552
                                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;
6553
            event = virDomainEventLifecycleNewFromObj(vm,
6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566
                                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 */
6567
                event2 = virDomainEventLifecycleNewFromObj(vm,
6568 6569 6570 6571 6572
                                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 已提交
6573
            virObjectUnref(event);
6574 6575 6576 6577
            event = NULL;

            if (was_stopped) {
                /* Transition 2 */
6578
                event = virDomainEventLifecycleNewFromObj(vm,
6579 6580 6581 6582
                                VIR_DOMAIN_EVENT_STARTED,
                                VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            } else if (was_running) {
                /* Transition 8 */
6583
                event = virDomainEventLifecycleNewFromObj(vm,
6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595
                                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);
6596
            event = virDomainEventLifecycleNewFromObj(vm,
6597 6598 6599 6600 6601 6602 6603 6604 6605
                                    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;

6606
            testObjectEventQueue(privconn, event);
6607
            event = virDomainEventLifecycleNewFromObj(vm,
6608 6609 6610
                            VIR_DOMAIN_EVENT_STARTED,
                            VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            if (paused) {
6611
                event2 = virDomainEventLifecycleNewFromObj(vm,
6612 6613 6614 6615 6616 6617 6618 6619
                                VIR_DOMAIN_EVENT_SUSPENDED,
                                VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
            }
        }
    }

    vm->current_snapshot = snap;
    ret = 0;
6620
 cleanup:
6621
    if (event) {
6622
        testObjectEventQueue(privconn, event);
6623
        testObjectEventQueue(privconn, event2);
C
Cole Robinson 已提交
6624
    } else {
C
Cédric Bosdonnat 已提交
6625
        virObjectUnref(event2);
6626
    }
6627
    virDomainObjEndAPI(&vm);
6628 6629 6630 6631 6632

    return ret;
}


6633

6634
static virHypervisorDriver testHypervisorDriver = {
6635
    .name = "Test",
6636 6637 6638
    .connectOpen = testConnectOpen, /* 0.1.1 */
    .connectClose = testConnectClose, /* 0.1.1 */
    .connectGetVersion = testConnectGetVersion, /* 0.1.1 */
6639
    .connectGetHostname = testConnectGetHostname, /* 0.6.3 */
6640
    .connectGetMaxVcpus = testConnectGetMaxVcpus, /* 0.3.2 */
6641
    .nodeGetInfo = testNodeGetInfo, /* 0.1.1 */
6642 6643 6644 6645
    .connectGetCapabilities = testConnectGetCapabilities, /* 0.2.1 */
    .connectListDomains = testConnectListDomains, /* 0.1.1 */
    .connectNumOfDomains = testConnectNumOfDomains, /* 0.1.1 */
    .connectListAllDomains = testConnectListAllDomains, /* 0.9.13 */
6646
    .domainCreateXML = testDomainCreateXML, /* 0.1.4 */
6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660
    .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 */
6661 6662
    .domainGetState = testDomainGetState, /* 0.9.2 */
    .domainSave = testDomainSave, /* 0.3.2 */
6663
    .domainSaveFlags = testDomainSaveFlags, /* 0.9.4 */
6664
    .domainRestore = testDomainRestore, /* 0.3.2 */
6665
    .domainRestoreFlags = testDomainRestoreFlags, /* 0.9.4 */
6666
    .domainCoreDump = testDomainCoreDump, /* 0.3.2 */
6667
    .domainCoreDumpWithFormat = testDomainCoreDumpWithFormat, /* 1.2.3 */
6668
    .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */
6669 6670 6671 6672
    .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */
    .domainGetVcpusFlags = testDomainGetVcpusFlags, /* 0.8.5 */
    .domainPinVcpu = testDomainPinVcpu, /* 0.7.3 */
    .domainGetVcpus = testDomainGetVcpus, /* 0.7.3 */
6673
    .domainGetVcpuPinInfo = testDomainGetVcpuPinInfo, /* 1.2.18 */
6674 6675
    .domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
    .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
6676 6677
    .connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
    .connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
6678 6679 6680
    .domainCreate = testDomainCreate, /* 0.1.11 */
    .domainCreateWithFlags = testDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = testDomainDefineXML, /* 0.1.11 */
6681
    .domainDefineXMLFlags = testDomainDefineXMLFlags, /* 1.2.12 */
6682
    .domainUndefine = testDomainUndefine, /* 0.1.11 */
6683
    .domainUndefineFlags = testDomainUndefineFlags, /* 0.9.4 */
6684 6685 6686
    .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
    .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
    .domainGetSchedulerType = testDomainGetSchedulerType, /* 0.3.2 */
6687 6688 6689 6690
    .domainGetSchedulerParameters = testDomainGetSchedulerParameters, /* 0.3.2 */
    .domainGetSchedulerParametersFlags = testDomainGetSchedulerParametersFlags, /* 0.9.2 */
    .domainSetSchedulerParameters = testDomainSetSchedulerParameters, /* 0.3.2 */
    .domainSetSchedulerParametersFlags = testDomainSetSchedulerParametersFlags, /* 0.9.2 */
6691 6692 6693
    .domainBlockStats = testDomainBlockStats, /* 0.7.0 */
    .domainInterfaceStats = testDomainInterfaceStats, /* 0.7.0 */
    .nodeGetCellsFreeMemory = testNodeGetCellsFreeMemory, /* 0.4.2 */
6694 6695 6696 6697
    .connectDomainEventRegister = testConnectDomainEventRegister, /* 0.6.0 */
    .connectDomainEventDeregister = testConnectDomainEventDeregister, /* 0.6.0 */
    .connectIsEncrypted = testConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = testConnectIsSecure, /* 0.7.3 */
6698 6699 6700
    .domainIsActive = testDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = testDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = testDomainIsUpdated, /* 0.8.6 */
6701 6702 6703
    .connectDomainEventRegisterAny = testConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = testConnectDomainEventDeregisterAny, /* 0.8.0 */
    .connectIsAlive = testConnectIsAlive, /* 0.9.8 */
6704
    .nodeGetCPUMap = testNodeGetCPUMap, /* 1.0.0 */
6705
    .domainScreenshot = testDomainScreenshot, /* 1.0.5 */
6706 6707
    .domainGetMetadata = testDomainGetMetadata, /* 1.1.3 */
    .domainSetMetadata = testDomainSetMetadata, /* 1.1.3 */
6708
    .connectGetCPUModelNames = testConnectGetCPUModelNames, /* 1.1.3 */
6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725
    .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 */
6726 6727 6728
    .domainSnapshotCreateXML = testDomainSnapshotCreateXML, /* 1.1.4 */
    .domainRevertToSnapshot = testDomainRevertToSnapshot, /* 1.1.4 */
    .domainSnapshotDelete = testDomainSnapshotDelete, /* 1.1.4 */
6729

E
Eric Blake 已提交
6730
    .connectBaselineCPU = testConnectBaselineCPU, /* 1.2.0 */
6731 6732 6733
};

static virNetworkDriver testNetworkDriver = {
6734 6735 6736 6737 6738
    .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 */
6739 6740
    .connectNetworkEventRegisterAny = testConnectNetworkEventRegisterAny, /* 1.2.1 */
    .connectNetworkEventDeregisterAny = testConnectNetworkEventDeregisterAny, /* 1.2.1 */
6741 6742 6743 6744
    .networkLookupByUUID = testNetworkLookupByUUID, /* 0.3.2 */
    .networkLookupByName = testNetworkLookupByName, /* 0.3.2 */
    .networkCreateXML = testNetworkCreateXML, /* 0.3.2 */
    .networkDefineXML = testNetworkDefineXML, /* 0.3.2 */
6745
    .networkUndefine = testNetworkUndefine, /* 0.3.2 */
6746
    .networkUpdate = testNetworkUpdate, /* 0.10.2 */
6747
    .networkCreate = testNetworkCreate, /* 0.3.2 */
6748 6749 6750 6751 6752 6753 6754
    .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 */
6755 6756
};

L
Laine Stump 已提交
6757
static virInterfaceDriver testInterfaceDriver = {
6758 6759 6760 6761 6762 6763
    .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 */
6764 6765 6766 6767 6768 6769
    .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 */
6770 6771 6772
    .interfaceChangeBegin = testInterfaceChangeBegin,   /* 0.9.2 */
    .interfaceChangeCommit = testInterfaceChangeCommit,  /* 0.9.2 */
    .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */
L
Laine Stump 已提交
6773 6774 6775
};


6776
static virStorageDriver testStorageDriver = {
6777 6778 6779 6780 6781 6782
    .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 */
6783 6784 6785
    .storagePoolLookupByName = testStoragePoolLookupByName, /* 0.5.0 */
    .storagePoolLookupByUUID = testStoragePoolLookupByUUID, /* 0.5.0 */
    .storagePoolLookupByVolume = testStoragePoolLookupByVolume, /* 0.5.0 */
6786 6787
    .storagePoolCreateXML = testStoragePoolCreateXML, /* 0.5.0 */
    .storagePoolDefineXML = testStoragePoolDefineXML, /* 0.5.0 */
6788 6789
    .storagePoolBuild = testStoragePoolBuild, /* 0.5.0 */
    .storagePoolUndefine = testStoragePoolUndefine, /* 0.5.0 */
6790
    .storagePoolCreate = testStoragePoolCreate, /* 0.5.0 */
6791 6792 6793 6794 6795 6796 6797
    .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 */
6798
    .storagePoolNumOfVolumes = testStoragePoolNumOfVolumes, /* 0.5.0 */
6799 6800 6801
    .storagePoolListVolumes = testStoragePoolListVolumes, /* 0.5.0 */
    .storagePoolListAllVolumes = testStoragePoolListAllVolumes, /* 0.10.2 */

6802 6803 6804 6805 6806 6807 6808 6809 6810
    .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 */
6811 6812
    .storagePoolIsActive = testStoragePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = testStoragePoolIsPersistent, /* 0.7.3 */
6813 6814
};

6815
static virNodeDeviceDriver testNodeDeviceDriver = {
6816 6817 6818 6819 6820 6821 6822 6823 6824
    .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 */
6825 6826
};

6827 6828 6829 6830 6831 6832 6833 6834
static virConnectDriver testConnectDriver = {
    .hypervisorDriver = &testHypervisorDriver,
    .interfaceDriver = &testInterfaceDriver,
    .networkDriver = &testNetworkDriver,
    .nodeDeviceDriver = &testNodeDeviceDriver,
    .nwfilterDriver = NULL,
    .secretDriver = NULL,
    .storageDriver = &testStorageDriver,
6835 6836
};

6837 6838 6839 6840 6841 6842 6843 6844
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
6845 6846
    return virRegisterConnectDriver(&testConnectDriver,
                                    false);
6847
}