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

24
#include <config.h>
25

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

35

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

65 66
#define VIR_FROM_THIS VIR_FROM_TEST

67 68
VIR_LOG_INIT("test.test_driver");

69

70 71 72 73 74
#define MAX_CPUS 128

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

#define MAX_CELLS 128
81

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

89
struct _testDriver {
90
    virMutex lock;
91

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

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

106 107 108 109 110 111 112 113 114 115
    /* immutable pointer, immutable object after being initialized with
     * testBuildCapabilities */
    virCapsPtr caps;

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

    /* immutable pointer, self-locking APIs */
    virDomainObjListPtr domains;
    virNetworkObjListPtr networks;
116
    virObjectEventStatePtr eventState;
117
};
118 119
typedef struct _testDriver testDriver;
typedef testDriver *testDriverPtr;
120

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

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

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

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

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

    VIR_FREE(driver);
}
158

159

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

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

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

    virObjectEventStateQueue(driver->eventState, event);
}

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

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

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

static void
testDomainDefNamespaceFree(void *data)
{
    testDomainNamespaceDefPtr nsdata = data;
196 197 198 199 200 201 202 203 204
    size_t i;

    if (!nsdata)
        return;

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

    VIR_FREE(nsdata->snap_nodes);
205 206 207 208 209 210 211 212 213 214
    VIR_FREE(nsdata);
}

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

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

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

231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
    n = virXPathNodeSet("./test:domainsnapshot", ctxt, &nodes);
    if (n < 0)
        goto error;

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

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

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

250 251 252 253 254 255 256
    tmp = virXPathBoolean("boolean(./test:transient)", ctxt);
    if (tmp == -1) {
        virReportError(VIR_ERR_XML_ERROR, "%s", _("invalid transient"));
        goto error;
    }
    nsdata->transient = tmp;

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

264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
    tmp = virXPathUInt("string(./test:runstate)", ctxt, &tmpuint);
    if (tmp == 0) {
        if (tmpuint >= VIR_DOMAIN_LAST) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("runstate '%d' out of range'"), tmpuint);
            goto error;
        }
        nsdata->runstate = tmpuint;
    } else if (tmp == -1) {
        nsdata->runstate = VIR_DOMAIN_RUNNING;
    } else if (tmp == -2) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid runstate"));
        goto error;
    }

280 281 282 283 284
    if (nsdata->transient && nsdata->runstate == VIR_DOMAIN_SHUTOFF) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
            _("transient domain cannot have runstate 'shutoff'"));
        goto error;
    }
C
Cole Robinson 已提交
285 286 287 288 289
    if (nsdata->hasManagedSave && nsdata->runstate != VIR_DOMAIN_SHUTOFF) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
            _("domain with managedsave data can only have runstate 'shutoff'"));
        goto error;
    }
290

291 292 293
    *data = nsdata;
    return 0;

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

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

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

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

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

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

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


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

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

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

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

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

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

367
    return caps;
368

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

374

375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
static testDriverPtr
testDriverNew(void)
{
    virDomainXMLNamespace ns = {
        .parse = testDomainDefNamespaceParse,
        .free = testDomainDefNamespaceFree,
    };
    testDriverPtr ret;

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

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

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

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

    return ret;

 error:
    testDriverFree(ret);
    return NULL;
}


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


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

L
Laine Stump 已提交
435 436 437 438 439 440 441 442 443 444 445
static const char *defaultInterfaceXML =
"<interface type=\"ethernet\" name=\"eth1\">"
"  <start mode=\"onboot\"/>"
"  <mac address=\"aa:bb:cc:dd:ee:ff\"/>"
"  <mtu size=\"1492\"/>"
"  <protocol family=\"ipv4\">"
"    <ip address=\"192.168.0.5\" prefix=\"24\"/>"
"    <route gateway=\"192.168.0.1\"/>"
"  </protocol>"
"</interface>";

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

455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
static const char *defaultPoolSourcesLogicalXML =
"<sources>\n"
"  <source>\n"
"    <device path='/dev/sda20'/>\n"
"    <name>testvg1</name>\n"
"    <format type='lvm2'/>\n"
"  </source>\n"
"  <source>\n"
"    <device path='/dev/sda21'/>\n"
"    <name>testvg2</name>\n"
"    <format type='lvm2'/>\n"
"  </source>\n"
"</sources>\n";

static const char *defaultPoolSourcesNetFSXML =
"<sources>\n"
"  <source>\n"
"    <host name='%s'/>\n"
"    <dir path='/testshare'/>\n"
"    <format type='nfs'/>\n"
"  </source>\n"
"</sources>\n";

478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
static const char *defaultNodeXML =
"<device>"
"  <name>computer</name>"
"  <capability type='system'>"
"    <hardware>"
"      <vendor>Libvirt</vendor>"
"      <version>Test driver</version>"
"      <serial>123456</serial>"
"      <uuid>11111111-2222-3333-4444-555555555555</uuid>"
"    </hardware>"
"    <firmware>"
"      <vendor>Libvirt</vendor>"
"      <version>Test Driver</version>"
"      <release_date>01/22/2007</release_date>"
"    </firmware>"
"  </capability>"
"</device>";

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

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

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

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

    return vm;
}

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

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

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

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

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

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

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

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

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

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

570
    return 0;
571 572
}

573

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

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

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

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

602
    if (virDomainObjSetDefTransient(privconn->caps,
603
                                    privconn->xmlopt,
604
                                    dom, 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, privconn->caps,
1986
                             VIR_DOMAIN_DEF_FORMAT_SECURE);
C
Cole Robinson 已提交
1987

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

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

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

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

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

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

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

2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064
static int
testDomainSave(virDomainPtr domain,
               const char *path)
{
    return testDomainSaveFlags(domain, path, NULL, 0);
}

static int
testDomainRestoreFlags(virConnectPtr conn,
                       const char *path,
                       const char *dxml,
                       unsigned int flags)
2065
{
2066
    testDriverPtr privconn = conn->privateData;
2067
    char *xml = NULL;
2068
    char magic[15];
2069 2070 2071
    int fd = -1;
    int len;
    virDomainDefPtr def = NULL;
2072
    virDomainObjPtr dom = NULL;
2073
    virObjectEventPtr event = NULL;
2074
    int ret = -1;
2075

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

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

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

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

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

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

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

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

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

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

2179

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

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

2202 2203 2204 2205 2206 2207 2208
    /* we don't support non-raw formats in test driver */
    if (dumpformat != VIR_DOMAIN_CORE_DUMP_FORMAT_RAW) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("kdump-compressed format is not supported here"));
        goto cleanup;
    }

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

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

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

static int
testDomainCoreDump(virDomainPtr domain,
                   const char *to,
                   unsigned int flags)
{
    return testDomainCoreDumpWithFormat(domain, to,
                                        VIR_DOMAIN_CORE_DUMP_FORMAT_RAW, flags);
}


static char *
testDomainGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED)
{
2240 2241 2242
    char *ret;

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

2246 2247 2248

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2392 2393
    ret = 0;

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

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

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

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

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

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

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

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

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

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

    virBitmapSetAll(allcpumap);

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

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

2457 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
    testDriverPtr privconn = domain->conn->privateData;
2595
    virDomainDefPtr def;
2596
    virDomainObjPtr privdom;
2597 2598
    char *ret = NULL;

2599 2600
    /* Flags checked by virDomainDefFormat */

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

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

2607 2608
    ret = virDomainDefFormat(def, privconn->caps,
                             virDomainDefFormatConvertXMLFlags(flags));
2609

2610
    virDomainObjEndAPI(&privdom);
2611
    return ret;
2612
}
2613

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

2618
    return virDomainObjListNumOfDomains(privconn->domains, false, NULL, NULL);
2619 2620
}

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

2626
    testDriverPtr privconn = conn->privateData;
2627 2628

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

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

    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
2646

2647 2648
    if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE;
2649

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

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

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

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

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

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

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

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, NULL);

2702 2703
    if (!(privdom = testDomObjFromDomain(dom)))
        return NULL;
2704 2705 2706 2707

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

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

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

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

2726 2727
    if (!(privdom = testDomObjFromDomain(dom)))
        return -1;
2728 2729 2730

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

2733
    virDomainObjEndAPI(&privdom);
2734 2735 2736 2737
    return ret;
}


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

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

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

2761
 cleanup:
2762
    testDriverUnlock(privconn);
2763
    return ret;
2764 2765 2766
}


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

2774 2775
    virCheckFlags(0, -1);

2776
    testDriverLock(privconn);
2777

2778
    if (!(privdom = testDomObjFromDomain(domain)))
2779
        goto cleanup;
2780

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

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

2792
    event = virDomainEventLifecycleNewFromObj(privdom,
2793 2794
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
2795
    ret = 0;
2796

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

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

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

2818 2819
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
                  VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
2820

2821

2822
    if (!(privdom = testDomObjFromDomain(domain)))
2823
        goto cleanup;
2824

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

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

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

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

2861
    ret = 0;
2862

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

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

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

2879 2880
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2881

2882
    *autostart = privdom->autostart;
2883

2884
    virDomainObjEndAPI(&privdom);
2885
    return 0;
2886 2887 2888 2889 2890 2891
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
2892 2893
    virDomainObjPtr privdom;

2894 2895
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2896

2897
    privdom->autostart = autostart ? 1 : 0;
2898

2899
    virDomainObjEndAPI(&privdom);
2900
    return 0;
2901
}
2902

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

2908 2909 2910
    if (nparams)
        *nparams = 1;

2911
    ignore_value(VIR_STRDUP(type, "fair"));
2912

2913 2914 2915
    return type;
}

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

2925 2926
    virCheckFlags(0, -1);

2927 2928
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2929

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

    *nparams = 1;
2937 2938
    ret = 0;

2939
 cleanup:
2940
    virDomainObjEndAPI(&privdom);
2941
    return ret;
2942
}
2943

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

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

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

2969 2970
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2971

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

2979 2980
    ret = 0;

2981
    virDomainObjEndAPI(&privdom);
2982
    return ret;
2983 2984
}

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

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

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

3008 3009
    if (!(privdom = testDomObjFromDomain(domain)))
        return ret;
3010

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

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

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

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

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

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

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

3087

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

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

3101 3102
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

3103
 cleanup:
3104
    virNetworkObjEndAPI(&net);
3105
    return ret;
3106
}
3107

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

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

3121 3122
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

3123
 cleanup:
3124
    virNetworkObjEndAPI(&net);
3125
    return ret;
3126 3127 3128
}


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

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

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

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

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

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

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

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

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

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

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

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

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

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

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

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

3210
 cleanup:
3211
    virNetworkObjEndAPI(&obj);
3212 3213 3214 3215
    return ret;
}


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

3224
    if ((def = virNetworkDefParseString(xml)) == NULL)
3225
        goto cleanup;
3226

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

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

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

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

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

3256
    if ((def = virNetworkDefParseString(xml)) == NULL)
3257
        goto cleanup;
3258

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

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

3267
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3268

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

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

3283
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3284 3285

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

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

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

3300
    virNetworkRemoveInactive(privconn->networks, privnet);
3301
    ret = 0;
3302

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

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

    virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
                  VIR_NETWORK_UPDATE_AFFECT_CONFIG,
                  -1);

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

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

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

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

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

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

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

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

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

3406 3407
    ret = 0;

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

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

E
Eric Blake 已提交
3421 3422
    virCheckFlags(0, NULL);

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

3429
    ret = virNetworkDefFormat(privnet->def, flags);
3430

3431
 cleanup:
3432
    virNetworkObjEndAPI(&privnet);
3433
    return ret;
3434 3435 3436
}

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

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

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

3454
    ignore_value(VIR_STRDUP(bridge, privnet->def->bridge));
3455

3456
 cleanup:
3457
    virNetworkObjEndAPI(&privnet);
3458 3459 3460 3461
    return bridge;
}

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

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

3474
    *autostart = privnet->autostart;
3475 3476
    ret = 0;

3477
 cleanup:
3478
    virNetworkObjEndAPI(&privnet);
3479
    return ret;
3480 3481 3482
}

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

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

3495
    privnet->autostart = autostart ? 1 : 0;
3496 3497
    ret = 0;

3498
 cleanup:
3499
    virNetworkObjEndAPI(&privnet);
3500
    return ret;
3501
}
3502

C
Cole Robinson 已提交
3503

L
Laine Stump 已提交
3504 3505 3506 3507 3508
/*
 * Physical host interface routines
 */


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

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

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

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

    return n;

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

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

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

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

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

    return n;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3670
 cleanup:
3671 3672 3673 3674 3675
    if (obj)
        virInterfaceObjUnlock(obj);
    return ret;
}

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

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

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

    privconn->transaction_running = true;

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

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

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

E
Eric Blake 已提交
3709 3710
    virCheckFlags(0, -1);

3711 3712 3713
    testDriverLock(privconn);

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

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

    ret = 0;

3725
 cleanup:
3726 3727 3728 3729 3730 3731
    testDriverUnlock(privconn);

    return ret;
}

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

E
Eric Blake 已提交
3737 3738
    virCheckFlags(0, -1);

3739 3740 3741
    testDriverLock(privconn);

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

3758
 cleanup:
3759 3760 3761
    testDriverUnlock(privconn);
    return ret;
}
3762

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

E
Eric Blake 已提交
3770 3771
    virCheckFlags(0, NULL);

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

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

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

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


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

E
Eric Blake 已提交
3799 3800
    virCheckFlags(0, NULL);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    privinterface->active = 1;
    ret = 0;

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

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

E
Eric Blake 已提交
3883 3884
    virCheckFlags(0, -1);

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

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

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

    privinterface->active = 0;
    ret = 0;

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



C
Cole Robinson 已提交
3911 3912 3913 3914
/*
 * Storage Driver routines
 */

3915

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

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

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

3926

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

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

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

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

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

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

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

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

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

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

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

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

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

    return numActive;
}

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

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

    return n;

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

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

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

    return numInactive;
}

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

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

    return n;

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

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

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

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

    return ret;
}
C
Cole Robinson 已提交
4099

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

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

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

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

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

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



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

E
Eric Blake 已提交
4152 4153
    virCheckFlags(0, -1);

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

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

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

    privpool->active = 1;
4171
    ret = 0;
C
Cole Robinson 已提交
4172

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

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

E
Eric Blake 已提交
4189 4190
    virCheckFlags(0, NULL);

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

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

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
4207
        ignore_value(VIR_STRDUP(ret, defaultPoolSourcesLogicalXML));
4208 4209 4210
        break;

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

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

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

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


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

E
Eric Blake 已提交
4242 4243
    virCheckFlags(0, NULL);

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

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

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

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

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

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

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

E
Eric Blake 已提交
4289 4290
    virCheckFlags(0, NULL);

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

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

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

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

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

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

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

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

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

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

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

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

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

E
Eric Blake 已提交
4361 4362
    virCheckFlags(0, -1);

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

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

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

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


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

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

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

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

    privpool->active = 0;

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

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


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

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

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

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

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

4451
    ret = 0;
C
Cole Robinson 已提交
4452

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


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

E
Eric Blake 已提交
4468 4469
    virCheckFlags(0, -1);

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

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

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

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


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

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

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

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

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

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

E
Eric Blake 已提交
4536 4537
    virCheckFlags(0, NULL);

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

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

4548
    ret = virStoragePoolDefFormat(privpool->def);
4549

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

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

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

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

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

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

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

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

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

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

    autostart = (autostart != 0);
    privpool->autostart = autostart;
4613 4614
    ret = 0;

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


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

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

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

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

4645 4646
    ret = privpool->volumes.count;

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

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

4663
    memset(names, 0, maxnames * sizeof(*names));
4664 4665

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

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


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

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

4687
    virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4688 4689 4690
    return n;

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

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

4700 4701 4702
static int
testStoragePoolListAllVolumes(virStoragePoolPtr obj,
                              virStorageVolPtr **vols,
4703 4704
                              unsigned int flags)
{
4705
    testDriverPtr privconn = obj->conn->privateData;
4706
    virStoragePoolObjPtr pool;
4707
    size_t i;
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 4735 4736
    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;
    }

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

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

    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
C
Cole Robinson 已提交
4767 4768

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

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

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


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

    privvol = virStorageVolDefFindByName(privpool, name);

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

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

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


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

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

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

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

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

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

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

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

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

    return ret;
C
Cole Robinson 已提交
4883 4884 4885
}

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

E
Eric Blake 已提交
4895 4896
    virCheckFlags(0, NULL);

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

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

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

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

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

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

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

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

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

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

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

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

E
Eric Blake 已提交
4969 4970
    virCheckFlags(0, NULL);

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

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

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

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

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

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

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

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

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

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

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

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

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

E
Eric Blake 已提交
5052 5053
    virCheckFlags(0, -1);

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

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


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

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

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


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

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

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

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


5102 5103
static int testStorageVolumeTypeForPool(int pooltype)
{
C
Cole Robinson 已提交
5104

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

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

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

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

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

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

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

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

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

E
Eric Blake 已提交
5170 5171
    virCheckFlags(0, NULL);

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

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

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

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

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

5197
    ret = virStorageVolDefFormat(privpool->def, privvol);
5198

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

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

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

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

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

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

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

5238
    ignore_value(VIR_STRDUP(ret, privvol->target.path));
5239

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

5246

5247
/* Node device implementations */
5248

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

E
Eric Blake 已提交
5258 5259
    virCheckFlags(0, -1);

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

E
Eric Blake 已提交
5281 5282
    virCheckFlags(0, -1);

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

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

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

    ret = virGetNodeDevice(conn, name);

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

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

E
Eric Blake 已提交
5341 5342
    virCheckFlags(0, NULL);

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

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

5354
    ret = virNodeDeviceDefFormat(obj->def);
5355

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

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

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

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

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

5387
 cleanup:
5388 5389 5390 5391 5392
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

5393

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

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

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

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

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


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

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

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

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

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

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

E
Eric Blake 已提交
5475 5476
    virCheckFlags(0, NULL);

5477 5478
    testDriverLock(driver);

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

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

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

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

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


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

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

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

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

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

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

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

5580 5581

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

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

    return ret;
}

5598

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

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

    return ret;
}

5613 5614

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

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

    return ret;
}

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

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

    return ret;
}


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

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

    return ret;
}

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

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

    return ret;
}

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

O
Osier Yang 已提交
5687
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
5688

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

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

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

    if (online)
        *online = 3;

P
Peter Krempa 已提交
5710
    return  8;
5711 5712
}

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

    virCheckFlags(0, NULL);

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

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

    return ret;
}

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

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

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

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

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

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

    return ret;
}


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

    virCheckFlags(0, -1);

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

    ret = vm->hasManagedSave;
5796

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

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

    virCheckFlags(0, -1);

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

    vm->hasManagedSave = false;
5812

5813
    virDomainObjEndAPI(&vm);
5814
    return 0;
C
Cole Robinson 已提交
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 5850 5851
/*
 * 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;
5852
    int n;
5853 5854 5855 5856 5857

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5858
        return -1;
5859 5860 5861

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

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

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

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5879
        return -1;
5880 5881 5882 5883

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

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

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

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5900
        return -1;
5901 5902 5903

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6019
        return -1;
6020 6021 6022

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

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

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

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

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

    virCheckFlags(0, NULL);

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

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

6077
 cleanup:
6078
    virDomainObjEndAPI(&vm);
6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093
    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)))
6094
        return NULL;
6095 6096 6097 6098 6099 6100

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

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

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

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

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

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6120
        return -1;
6121 6122 6123 6124

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

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


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

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6140
        return -1;
6141

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

    ret = 1;

6147
 cleanup:
6148
    virDomainObjEndAPI(&vm);
6149 6150 6151
    return ret;
}

6152 6153 6154 6155 6156 6157
static int
testDomainSnapshotAlignDisks(virDomainObjPtr vm,
                             virDomainSnapshotDefPtr def,
                             unsigned int flags)
{
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
E
Eric Blake 已提交
6158
    bool align_match = true;
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 6185 6186

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

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

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

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

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

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

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

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

    snapshot = virGetDomainSnapshot(domain, snap->def->name);
6275
 cleanup:
6276 6277 6278 6279
    VIR_FREE(xml);
    if (vm) {
        if (snapshot) {
            virDomainSnapshotObjPtr other;
6280 6281
            if (update_current)
                vm->current_snapshot = snap;
6282 6283 6284 6285 6286 6287 6288
            other = virDomainSnapshotFindByName(vm->snapshots,
                                                snap->def->parent);
            snap->parent = other;
            other->nchildren++;
            snap->sibling = other->first_child;
            other->first_child = snap;
        }
6289
        virDomainObjEndAPI(&vm);
6290
    }
6291
    testObjectEventQueue(privconn, event);
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 6332 6333
    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;

6334
    if (rep->err < 0)
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 6375 6376
        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) {
6377
            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)
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 6419 6420
                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;
6421
 cleanup:
6422
    virDomainObjEndAPI(&vm);
6423 6424 6425 6426 6427 6428 6429
    return ret;
}

static int
testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                           unsigned int flags)
{
6430
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6431 6432
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
6433 6434
    virObjectEventPtr event = NULL;
    virObjectEventPtr event2 = NULL;
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 6524 6525
    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);
6526
                event = virDomainEventLifecycleNewFromObj(vm,
6527 6528
                            VIR_DOMAIN_EVENT_STOPPED,
                            VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
6529
                testObjectEventQueue(privconn, event);
6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540
                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. */
6541
                event = virDomainEventLifecycleNewFromObj(vm,
6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554
                                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;
6555
            event = virDomainEventLifecycleNewFromObj(vm,
6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568
                                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 */
6569
                event2 = virDomainEventLifecycleNewFromObj(vm,
6570 6571 6572 6573 6574
                                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 已提交
6575
            virObjectUnref(event);
6576 6577 6578 6579
            event = NULL;

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

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

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

    return ret;
}


6635

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

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

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

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


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

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

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

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

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