test_driver.c 192.4 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

    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;
2578 2579
        else if (def->cpumask)
            bitmap = def->cpumask;
2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593
        else
            bitmap = allcpumap;

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

    ret = ncpumaps;

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

2594
static char *testDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
2595
{
2596
    testDriverPtr privconn = domain->conn->privateData;
2597
    virDomainDefPtr def;
2598
    virDomainObjPtr privdom;
2599 2600
    char *ret = NULL;

2601 2602
    /* Flags checked by virDomainDefFormat */

2603 2604
    if (!(privdom = testDomObjFromDomain(domain)))
        return NULL;
2605

2606 2607
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
2608

2609 2610
    ret = virDomainDefFormat(def, privconn->caps,
                             virDomainDefFormatConvertXMLFlags(flags));
2611

2612
    virDomainObjEndAPI(&privdom);
2613
    return ret;
2614
}
2615

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

2620
    return virDomainObjListNumOfDomains(privconn->domains, false, NULL, NULL);
2621 2622
}

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

2628
    testDriverPtr privconn = conn->privateData;
2629 2630

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

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

    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
2648

2649 2650
    if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE;
2651

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

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

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

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

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

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

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

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, NULL);

2704 2705
    if (!(privdom = testDomObjFromDomain(dom)))
        return NULL;
2706 2707 2708 2709

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

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

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

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

2728 2729
    if (!(privdom = testDomObjFromDomain(dom)))
        return -1;
2730 2731 2732

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

2735
    virDomainObjEndAPI(&privdom);
2736 2737 2738 2739
    return ret;
}


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

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

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

2763
 cleanup:
2764
    testDriverUnlock(privconn);
2765
    return ret;
2766 2767 2768
}


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

2776 2777
    virCheckFlags(0, -1);

2778
    testDriverLock(privconn);
2779

2780
    if (!(privdom = testDomObjFromDomain(domain)))
2781
        goto cleanup;
2782

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

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

2794
    event = virDomainEventLifecycleNewFromObj(privdom,
2795 2796
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
2797
    ret = 0;
2798

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

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

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

2820 2821
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
                  VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
2822

2823

2824
    if (!(privdom = testDomObjFromDomain(domain)))
2825
        goto cleanup;
2826

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

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

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

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

2863
    ret = 0;
2864

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

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

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

2881 2882
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2883

2884
    *autostart = privdom->autostart;
2885

2886
    virDomainObjEndAPI(&privdom);
2887
    return 0;
2888 2889 2890 2891 2892 2893
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
2894 2895
    virDomainObjPtr privdom;

2896 2897
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2898

2899
    privdom->autostart = autostart ? 1 : 0;
2900

2901
    virDomainObjEndAPI(&privdom);
2902
    return 0;
2903
}
2904

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

2910 2911 2912
    if (nparams)
        *nparams = 1;

2913
    ignore_value(VIR_STRDUP(type, "fair"));
2914

2915 2916 2917
    return type;
}

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

2927 2928
    virCheckFlags(0, -1);

2929 2930
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2931

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

    *nparams = 1;
2939 2940
    ret = 0;

2941
 cleanup:
2942
    virDomainObjEndAPI(&privdom);
2943
    return ret;
2944
}
2945

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

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

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

2971 2972
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2973

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

2981 2982
    ret = 0;

2983
    virDomainObjEndAPI(&privdom);
2984
    return ret;
2985 2986
}

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

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

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

3010 3011
    if (!(privdom = testDomObjFromDomain(domain)))
        return ret;
3012

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

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

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

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

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

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

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

3089

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

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

3103 3104
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

3105
 cleanup:
3106
    virNetworkObjEndAPI(&net);
3107
    return ret;
3108
}
3109

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

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

3123 3124
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

3125
 cleanup:
3126
    virNetworkObjEndAPI(&net);
3127
    return ret;
3128 3129 3130
}


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

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

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

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

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

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

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

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

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

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

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

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

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

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

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

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

3212
 cleanup:
3213
    virNetworkObjEndAPI(&obj);
3214 3215 3216 3217
    return ret;
}


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

3226
    if ((def = virNetworkDefParseString(xml)) == NULL)
3227
        goto cleanup;
3228

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

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

3240
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3241

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

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

3258
    if ((def = virNetworkDefParseString(xml)) == NULL)
3259
        goto cleanup;
3260

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

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

3269
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3270

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

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

3285
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3286 3287

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

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

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

3302
    virNetworkRemoveInactive(privconn->networks, privnet);
3303
    ret = 0;
3304

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

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

    virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
                  VIR_NETWORK_UPDATE_AFFECT_CONFIG,
                  -1);

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

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

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

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

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

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

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

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

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

3408 3409
    ret = 0;

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

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

E
Eric Blake 已提交
3423 3424
    virCheckFlags(0, NULL);

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

3431
    ret = virNetworkDefFormat(privnet->def, flags);
3432

3433
 cleanup:
3434
    virNetworkObjEndAPI(&privnet);
3435
    return ret;
3436 3437 3438
}

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

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

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

3456
    ignore_value(VIR_STRDUP(bridge, privnet->def->bridge));
3457

3458
 cleanup:
3459
    virNetworkObjEndAPI(&privnet);
3460 3461 3462 3463
    return bridge;
}

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

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

3476
    *autostart = privnet->autostart;
3477 3478
    ret = 0;

3479
 cleanup:
3480
    virNetworkObjEndAPI(&privnet);
3481
    return ret;
3482 3483 3484
}

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

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

3497
    privnet->autostart = autostart ? 1 : 0;
3498 3499
    ret = 0;

3500
 cleanup:
3501
    virNetworkObjEndAPI(&privnet);
3502
    return ret;
3503
}
3504

C
Cole Robinson 已提交
3505

L
Laine Stump 已提交
3506 3507 3508 3509 3510
/*
 * Physical host interface routines
 */


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

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

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

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

    return n;

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

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

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

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

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

    return n;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3672
 cleanup:
3673 3674 3675 3676 3677
    if (obj)
        virInterfaceObjUnlock(obj);
    return ret;
}

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

E
Eric Blake 已提交
3684 3685
    virCheckFlags(0, -1);

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

    privconn->transaction_running = true;

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

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

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

E
Eric Blake 已提交
3711 3712
    virCheckFlags(0, -1);

3713 3714 3715
    testDriverLock(privconn);

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

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

    ret = 0;

3727
 cleanup:
3728 3729 3730 3731 3732 3733
    testDriverUnlock(privconn);

    return ret;
}

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

E
Eric Blake 已提交
3739 3740
    virCheckFlags(0, -1);

3741 3742 3743
    testDriverLock(privconn);

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

3760
 cleanup:
3761 3762 3763
    testDriverUnlock(privconn);
    return ret;
}
3764

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

E
Eric Blake 已提交
3772 3773
    virCheckFlags(0, NULL);

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

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

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

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


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

E
Eric Blake 已提交
3801 3802
    virCheckFlags(0, NULL);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    privinterface->active = 1;
    ret = 0;

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

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

E
Eric Blake 已提交
3885 3886
    virCheckFlags(0, -1);

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

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

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

    privinterface->active = 0;
    ret = 0;

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



C
Cole Robinson 已提交
3913 3914 3915 3916
/*
 * Storage Driver routines
 */

3917

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

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

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

3928

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

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

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

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

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

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

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

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

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

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

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

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

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

    return numActive;
}

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

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

    return n;

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

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

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

    return numInactive;
}

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

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

    return n;

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

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

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

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

    return ret;
}
C
Cole Robinson 已提交
4101

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

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

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

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

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

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



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

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

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

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

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

    privpool->active = 1;
4173
    ret = 0;
C
Cole Robinson 已提交
4174

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

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

E
Eric Blake 已提交
4191 4192
    virCheckFlags(0, NULL);

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

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

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
4209
        ignore_value(VIR_STRDUP(ret, defaultPoolSourcesLogicalXML));
4210 4211 4212
        break;

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

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

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

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


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

E
Eric Blake 已提交
4244 4245
    virCheckFlags(0, NULL);

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

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

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

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

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

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

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

E
Eric Blake 已提交
4291 4292
    virCheckFlags(0, NULL);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

    privpool->active = 0;

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

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


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

E
Eric Blake 已提交
4435 4436
    virCheckFlags(0, -1);

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

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

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

4453
    ret = 0;
C
Cole Robinson 已提交
4454

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


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

E
Eric Blake 已提交
4470 4471
    virCheckFlags(0, -1);

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

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

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

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


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

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

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

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

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

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

E
Eric Blake 已提交
4538 4539
    virCheckFlags(0, NULL);

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

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

4550
    ret = virStoragePoolDefFormat(privpool->def);
4551

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

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

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

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

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

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

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

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

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

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

    autostart = (autostart != 0);
    privpool->autostart = autostart;
4615 4616
    ret = 0;

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


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

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

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

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

4647 4648
    ret = privpool->volumes.count;

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

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

4665
    memset(names, 0, maxnames * sizeof(*names));
4666 4667

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

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


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

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

4689
    virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4690 4691 4692
    return n;

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

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

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

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

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

    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
C
Cole Robinson 已提交
4769 4770

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

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

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


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

    privvol = virStorageVolDefFindByName(privpool, name);

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

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

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


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

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

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

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

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

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

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

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

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

    return ret;
C
Cole Robinson 已提交
4885 4886 4887
}

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

E
Eric Blake 已提交
4897 4898
    virCheckFlags(0, NULL);

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

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

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

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

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

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

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

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

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

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

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

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

E
Eric Blake 已提交
4971 4972
    virCheckFlags(0, NULL);

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

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

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

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

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

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

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

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

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

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

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

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

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

E
Eric Blake 已提交
5054 5055
    virCheckFlags(0, -1);

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

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


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

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

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


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

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

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

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


5104 5105
static int testStorageVolumeTypeForPool(int pooltype)
{
C
Cole Robinson 已提交
5106

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

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

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

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

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

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

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

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

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

E
Eric Blake 已提交
5172 5173
    virCheckFlags(0, NULL);

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

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

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

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

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

5199
    ret = virStorageVolDefFormat(privpool->def, privvol);
5200

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

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

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

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

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

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

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

5240
    ignore_value(VIR_STRDUP(ret, privvol->target.path));
5241

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

5248

5249
/* Node device implementations */
5250

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

E
Eric Blake 已提交
5260 5261
    virCheckFlags(0, -1);

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

E
Eric Blake 已提交
5283 5284
    virCheckFlags(0, -1);

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

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

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

    ret = virGetNodeDevice(conn, name);

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

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

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

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

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

5356
    ret = virNodeDeviceDefFormat(obj->def);
5357

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

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

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

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

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

5389
 cleanup:
5390 5391 5392 5393 5394
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

5395

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

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

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

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

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


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

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

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

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

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

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

E
Eric Blake 已提交
5477 5478
    virCheckFlags(0, NULL);

5479 5480
    testDriverLock(driver);

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

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

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

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

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


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

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

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

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

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

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

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

5582 5583

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

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

    return ret;
}

5600

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

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

    return ret;
}

5615 5616

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

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

    return ret;
}

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

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

    return ret;
}


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

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

    return ret;
}

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

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

    return ret;
}

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

O
Osier Yang 已提交
5689
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
5690

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

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

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

    if (online)
        *online = 3;

P
Peter Krempa 已提交
5712
    return  8;
5713 5714
}

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

    virCheckFlags(0, NULL);

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

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

    return ret;
}

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

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

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

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

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

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

    return ret;
}


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

    virCheckFlags(0, -1);

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

    ret = vm->hasManagedSave;
5798

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

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

    virCheckFlags(0, -1);

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

    vm->hasManagedSave = false;
5814

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

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5860
        return -1;
5861 5862 5863

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

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

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

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5881
        return -1;
5882 5883 5884 5885

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

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

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

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5902
        return -1;
5903 5904 5905

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6021
        return -1;
6022 6023 6024

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

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

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

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

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

    virCheckFlags(0, NULL);

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

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

6079
 cleanup:
6080
    virDomainObjEndAPI(&vm);
6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091
    return snapshot;
}

static char *
testDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
                             unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    char *xml = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    char uuidstr[VIR_UUID_STRING_BUFLEN];
6092
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6093 6094 6095 6096

    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6097
        return NULL;
6098 6099 6100 6101 6102 6103

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

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

6104
    xml = virDomainSnapshotDefFormat(uuidstr, snap->def, privconn->caps,
6105 6106
                                     virDomainDefFormatConvertXMLFlags(flags),
                                     0);
6107

6108
 cleanup:
6109
    virDomainObjEndAPI(&vm);
6110 6111 6112 6113 6114 6115 6116 6117
    return xml;
}

static int
testDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6118
    int ret;
6119 6120 6121 6122

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6123
        return -1;
6124 6125 6126 6127

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

6128
    virDomainObjEndAPI(&vm);
6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142
    return ret;
}


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

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6143
        return -1;
6144

C
Cole Robinson 已提交
6145
    if (!testSnapObjFromSnapshot(vm, snapshot))
6146 6147 6148 6149
        goto cleanup;

    ret = 1;

6150
 cleanup:
6151
    virDomainObjEndAPI(&vm);
6152 6153 6154
    return ret;
}

6155 6156 6157 6158 6159 6160
static int
testDomainSnapshotAlignDisks(virDomainObjPtr vm,
                             virDomainSnapshotDefPtr def,
                             unsigned int flags)
{
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
E
Eric Blake 已提交
6161
    bool align_match = true;
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 6187 6188 6189

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

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

6221 6222 6223 6224 6225
    if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)))
        update_current = false;
    if (redefine)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;

6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240
    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;

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

6252
        if (testDomainSnapshotAlignDisks(vm, def, flags) < 0)
6253 6254 6255
            goto cleanup;
    }

6256 6257 6258 6259
    if (!snap) {
        if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
            goto cleanup;
        def = NULL;
6260 6261
    }

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

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

6337
    if (rep->err < 0)
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 6377 6378 6379
        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) {
6380
            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)
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 6421 6422 6423
                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;
6424
 cleanup:
6425
    virDomainObjEndAPI(&vm);
6426 6427 6428 6429 6430 6431 6432
    return ret;
}

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

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

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

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

    return ret;
}


6638

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

E
Eric Blake 已提交
6735
    .connectBaselineCPU = testConnectBaselineCPU, /* 1.2.0 */
6736 6737 6738
};

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

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


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

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

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

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

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