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

64 65
#define VIR_FROM_THIS VIR_FROM_TEST

66 67
VIR_LOG_INIT("test.test_driver");

68

69 70 71 72 73
#define MAX_CPUS 128

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

#define MAX_CELLS 128
80

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

88
struct _testDriver {
89
    virMutex lock;
90

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

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

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

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

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

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

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
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);
}
157

158

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

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

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

    virObjectEventStateQueue(driver->eventState, event);
}

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

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

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

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

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

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

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

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

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

290 291 292
    *data = nsdata;
    return 0;

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

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

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

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

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

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

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


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

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

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

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

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

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

366
    return caps;
367

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

373

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

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

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

    return ret;

 error:
    testDriverFree(ret);
    return NULL;
}


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


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

L
Laine Stump 已提交
434 435 436 437 438 439 440 441 442 443 444
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 已提交
445 446 447
static const char *defaultPoolXML =
"<pool type='dir'>"
"  <name>default-pool</name>"
448
"  <uuid>dfe224cb-28fb-8dd0-c4b2-64eb3f0f4566</uuid>"
C
Cole Robinson 已提交
449 450 451 452 453
"  <target>"
"    <path>/default-pool</path>"
"  </target>"
"</pool>";

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

477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
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>";

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

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

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

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

    return vm;
}

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

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

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

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

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

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

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

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

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

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

569
    return 0;
570 571
}

572

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

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

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

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

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

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

615 616 617 618 619 620 621

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

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

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

    conn->privateData = privconn;
646

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

649
    /* Numa setup */
650 651 652 653 654
    privconn->numCells = 2;
    for (u = 0; u < 2; ++u) {
        privconn->cells[u].numCpus = 8;
        privconn->cells[u].mem = (u + 1) * 2048 * 1024;
    }
655
    for (u = 0; u < 16; u++) {
656
        virBitmapPtr siblings = virBitmapNew(16);
657
        if (!siblings)
658 659 660 661 662 663
            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;
664 665
    }

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

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

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

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

691
    virObjectUnlock(domobj);
692

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

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

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

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

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

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

737 738
    defaultConn = privconn;

739
    virMutexUnlock(&defaultLock);
740

741 742
    return VIR_DRV_OPEN_SUCCESS;

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


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

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

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

C
Cole Robinson 已提交
785 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
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;
    }

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

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

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

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

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

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

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

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

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

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

910
static int
911
testParseDomainSnapshots(testDriverPtr privconn,
912 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
                         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;
962
 error:
963 964 965
    return ret;
}

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

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

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

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

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

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

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

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

1022
        virObjectUnlock(obj);
1023
    }
1024

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int
C
Cole Robinson 已提交
1111
testOpenVolumesForPool(const char *file,
1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
                       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);
1128
    if (num < 0)
1129 1130 1131
        goto error;

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

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

        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;
1150 1151
        if (VIR_APPEND_ELEMENT_COPY(pool->volumes.objs, pool->volumes.count, def) < 0)
            goto error;
1152

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        virNodeDeviceObjUnlock(obj);
    }

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

1257
static int
1258
testParseAuthUsers(testDriverPtr privconn,
1259 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
                   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;
1292
 error:
1293 1294 1295
    VIR_FREE(nodes);
    return ret;
}
1296 1297 1298

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

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

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

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

1315
    if (!(doc = virXMLParseFileCtxt(file, &ctxt)))
1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328
        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 已提交
1329
    if (testParseDomains(privconn, file, ctxt) < 0)
1330
        goto error;
C
Cole Robinson 已提交
1331
    if (testParseNetworks(privconn, file, ctxt) < 0)
1332
        goto error;
C
Cole Robinson 已提交
1333
    if (testParseInterfaces(privconn, file, ctxt) < 0)
1334
        goto error;
C
Cole Robinson 已提交
1335
    if (testParseStorage(privconn, file, ctxt) < 0)
1336
        goto error;
C
Cole Robinson 已提交
1337
    if (testParseNodedevs(privconn, file, ctxt) < 0)
1338
        goto error;
1339 1340
    if (testParseAuthUsers(privconn, ctxt) < 0)
        goto error;
1341

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

1346
    return 0;
1347 1348

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

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

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

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

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

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

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

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

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

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

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

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

1451
    return VIR_DRV_OPEN_SUCCESS;
1452 1453
}

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

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

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

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

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

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

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


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

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

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

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

1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528
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;
}

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

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

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

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

1558
    return count;
1559 1560
}

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

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

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

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

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

    ret = obj->persistent;

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

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

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

1604 1605 1606 1607
    virCheckFlags(VIR_DOMAIN_START_VALIDATE, NULL);

    if (flags & VIR_DOMAIN_START_VALIDATE)
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE;
1608

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

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

1624
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_BOOTED) < 0)
1625
        goto cleanup;
1626

1627
    event = virDomainEventLifecycleNewFromObj(dom,
1628 1629 1630
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);

1631
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1632
    if (ret)
1633
        ret->id = dom->def->id;
1634

1635
 cleanup:
1636
    if (dom)
1637
        virObjectUnlock(dom);
1638
    testObjectEventQueue(privconn, event);
1639
    virDomainDefFree(def);
1640
    testDriverUnlock(privconn);
1641
    return ret;
1642 1643 1644
}


1645
static virDomainPtr testDomainLookupByID(virConnectPtr conn,
1646
                                         int id)
1647
{
1648
    testDriverPtr privconn = conn->privateData;
1649 1650
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1651

1652
    if (!(dom = virDomainObjListFindByID(privconn->domains, id))) {
1653
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1654
        goto cleanup;
1655 1656
    }

1657
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1658 1659 1660
    if (ret)
        ret->id = dom->def->id;

1661
 cleanup:
1662
    if (dom)
1663
        virObjectUnlock(dom);
1664
    return ret;
1665 1666
}

1667
static virDomainPtr testDomainLookupByUUID(virConnectPtr conn,
1668
                                           const unsigned char *uuid)
1669
{
1670
    testDriverPtr privconn = conn->privateData;
1671
    virDomainPtr ret = NULL;
1672
    virDomainObjPtr dom;
1673

1674
    if (!(dom = virDomainObjListFindByUUID(privconn->domains, uuid))) {
1675
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1676
        goto cleanup;
1677
    }
1678

1679
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1680 1681 1682
    if (ret)
        ret->id = dom->def->id;

1683
 cleanup:
1684
    if (dom)
1685
        virObjectUnlock(dom);
1686
    return ret;
1687 1688
}

1689
static virDomainPtr testDomainLookupByName(virConnectPtr conn,
1690
                                           const char *name)
1691
{
1692
    testDriverPtr privconn = conn->privateData;
1693 1694
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1695

1696
    if (!(dom = virDomainObjListFindByName(privconn->domains, name))) {
1697
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1698
        goto cleanup;
1699
    }
1700

1701
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1702 1703 1704
    if (ret)
        ret->id = dom->def->id;

1705
 cleanup:
1706
    virDomainObjEndAPI(&dom);
1707
    return ret;
1708 1709
}

1710 1711 1712
static int testConnectListDomains(virConnectPtr conn,
                                  int *ids,
                                  int maxids)
1713
{
1714
    testDriverPtr privconn = conn->privateData;
1715

1716 1717
    return virDomainObjListGetActiveIDs(privconn->domains, ids, maxids,
                                        NULL, NULL);
1718 1719
}

1720
static int testDomainDestroy(virDomainPtr domain)
1721
{
1722
    testDriverPtr privconn = domain->conn->privateData;
1723
    virDomainObjPtr privdom;
1724
    virObjectEventPtr event = NULL;
1725
    int ret = -1;
1726 1727


1728
    if (!(privdom = testDomObjFromDomain(domain)))
1729
        goto cleanup;
1730

J
Jiri Denemark 已提交
1731
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_DESTROYED);
1732
    event = virDomainEventLifecycleNewFromObj(privdom,
1733 1734
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
1735

1736 1737
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
1738 1739

    ret = 0;
1740
 cleanup:
1741
    virDomainObjEndAPI(&privdom);
1742
    testObjectEventQueue(privconn, event);
1743
    return ret;
1744 1745
}

1746
static int testDomainResume(virDomainPtr domain)
1747
{
1748
    testDriverPtr privconn = domain->conn->privateData;
1749
    virDomainObjPtr privdom;
1750
    virObjectEventPtr event = NULL;
1751
    int ret = -1;
1752

1753 1754
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1755

J
Jiri Denemark 已提交
1756
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_PAUSED) {
1757 1758
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"),
                       domain->name);
1759
        goto cleanup;
1760
    }
1761

J
Jiri Denemark 已提交
1762 1763
    virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                         VIR_DOMAIN_RUNNING_UNPAUSED);
1764
    event = virDomainEventLifecycleNewFromObj(privdom,
1765 1766
                                     VIR_DOMAIN_EVENT_RESUMED,
                                     VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
1767 1768
    ret = 0;

1769
 cleanup:
1770
    virDomainObjEndAPI(&privdom);
1771
    testObjectEventQueue(privconn, event);
1772
    return ret;
1773 1774
}

1775
static int testDomainSuspend(virDomainPtr domain)
1776
{
1777
    testDriverPtr privconn = domain->conn->privateData;
1778
    virDomainObjPtr privdom;
1779
    virObjectEventPtr event = NULL;
1780
    int ret = -1;
J
Jiri Denemark 已提交
1781
    int state;
1782

1783 1784
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1785

J
Jiri Denemark 已提交
1786 1787
    state = virDomainObjGetState(privdom, NULL);
    if (state == VIR_DOMAIN_SHUTOFF || state == VIR_DOMAIN_PAUSED) {
1788 1789
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"),
                       domain->name);
1790
        goto cleanup;
1791
    }
1792

J
Jiri Denemark 已提交
1793
    virDomainObjSetState(privdom, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
1794
    event = virDomainEventLifecycleNewFromObj(privdom,
1795 1796
                                     VIR_DOMAIN_EVENT_SUSPENDED,
                                     VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
1797 1798
    ret = 0;

1799
 cleanup:
1800
    virDomainObjEndAPI(&privdom);
1801
    testObjectEventQueue(privconn, event);
1802
    return ret;
1803 1804
}

1805
static int testDomainShutdownFlags(virDomainPtr domain,
1806
                                   unsigned int flags)
1807
{
1808
    testDriverPtr privconn = domain->conn->privateData;
1809
    virDomainObjPtr privdom;
1810
    virObjectEventPtr event = NULL;
1811
    int ret = -1;
1812

1813 1814
    virCheckFlags(0, -1);

1815

1816
    if (!(privdom = testDomObjFromDomain(domain)))
1817
        goto cleanup;
1818

J
Jiri Denemark 已提交
1819
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
1820 1821
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("domain '%s' not running"), domain->name);
1822
        goto cleanup;
1823
    }
1824

J
Jiri Denemark 已提交
1825
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1826
    event = virDomainEventLifecycleNewFromObj(privdom,
1827 1828
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1829

1830 1831
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
1832

1833
    ret = 0;
1834
 cleanup:
1835
    virDomainObjEndAPI(&privdom);
1836
    testObjectEventQueue(privconn, event);
1837
    return ret;
1838 1839
}

1840
static int testDomainShutdown(virDomainPtr domain)
1841
{
1842
    return testDomainShutdownFlags(domain, 0);
1843 1844
}

1845
/* Similar behaviour as shutdown */
1846
static int testDomainReboot(virDomainPtr domain,
1847
                            unsigned int action ATTRIBUTE_UNUSED)
1848
{
1849
    testDriverPtr privconn = domain->conn->privateData;
1850
    virDomainObjPtr privdom;
1851
    virObjectEventPtr event = NULL;
1852
    int ret = -1;
1853 1854


1855
    if (!(privdom = testDomObjFromDomain(domain)))
1856
        goto cleanup;
1857

J
Jiri Denemark 已提交
1858 1859 1860
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTDOWN,
                         VIR_DOMAIN_SHUTDOWN_USER);

1861 1862
    switch (privdom->def->onReboot) {
    case VIR_DOMAIN_LIFECYCLE_DESTROY:
J
Jiri Denemark 已提交
1863 1864
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1865 1866
        break;

1867
    case VIR_DOMAIN_LIFECYCLE_RESTART:
J
Jiri Denemark 已提交
1868 1869
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
1870 1871
        break;

1872
    case VIR_DOMAIN_LIFECYCLE_PRESERVE:
J
Jiri Denemark 已提交
1873 1874
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1875 1876
        break;

1877
    case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME:
J
Jiri Denemark 已提交
1878 1879
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
1880
        break;
1881

1882
    default:
J
Jiri Denemark 已提交
1883 1884
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1885 1886
        break;
    }
1887

J
Jiri Denemark 已提交
1888 1889
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1890
        event = virDomainEventLifecycleNewFromObj(privdom,
1891 1892
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1893

1894 1895
        if (!privdom->persistent)
            virDomainObjListRemove(privconn->domains, privdom);
1896 1897
    }

1898
    ret = 0;
1899
 cleanup:
1900
    virDomainObjEndAPI(&privdom);
1901
    testObjectEventQueue(privconn, event);
1902
    return ret;
1903 1904
}

1905
static int testDomainGetInfo(virDomainPtr domain,
1906
                             virDomainInfoPtr info)
1907
{
1908
    struct timeval tv;
1909
    virDomainObjPtr privdom;
1910
    int ret = -1;
1911

1912 1913
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1914 1915

    if (gettimeofday(&tv, NULL) < 0) {
1916 1917
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("getting time of day"));
1918
        goto cleanup;
1919 1920
    }

J
Jiri Denemark 已提交
1921
    info->state = virDomainObjGetState(privdom, NULL);
1922
    info->memory = privdom->def->mem.cur_balloon;
1923
    info->maxMem = virDomainDefGetMemoryActual(privdom->def);
1924 1925
    info->nrVirtCpu = privdom->def->vcpus;
    info->cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
1926 1927
    ret = 0;

1928
 cleanup:
1929
    virDomainObjEndAPI(&privdom);
1930
    return ret;
1931 1932
}

1933 1934 1935 1936 1937 1938 1939 1940 1941 1942
static int
testDomainGetState(virDomainPtr domain,
                   int *state,
                   int *reason,
                   unsigned int flags)
{
    virDomainObjPtr privdom;

    virCheckFlags(0, -1);

1943 1944
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1945

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

1948
    virDomainObjEndAPI(&privdom);
1949 1950

    return 0;
1951 1952
}

1953 1954
#define TEST_SAVE_MAGIC "TestGuestMagic"

1955 1956 1957
static int
testDomainSaveFlags(virDomainPtr domain, const char *path,
                    const char *dxml, unsigned int flags)
1958
{
1959
    testDriverPtr privconn = domain->conn->privateData;
1960 1961 1962
    char *xml = NULL;
    int fd = -1;
    int len;
1963
    virDomainObjPtr privdom;
1964
    virObjectEventPtr event = NULL;
1965
    int ret = -1;
1966

1967 1968
    virCheckFlags(0, -1);
    if (dxml) {
1969 1970
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1971 1972 1973
        return -1;
    }

1974

1975
    if (!(privdom = testDomObjFromDomain(domain)))
1976
        goto cleanup;
1977

1978
    xml = virDomainDefFormat(privdom->def,
1979
                             VIR_DOMAIN_DEF_FORMAT_SECURE);
C
Cole Robinson 已提交
1980

1981
    if (xml == NULL) {
1982
        virReportSystemError(errno,
1983 1984
                             _("saving domain '%s' failed to allocate space for metadata"),
                             domain->name);
1985
        goto cleanup;
1986
    }
1987 1988

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

2014
    if (VIR_CLOSE(fd) < 0) {
2015
        virReportSystemError(errno,
2016 2017
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
2018
        goto cleanup;
2019
    }
2020 2021
    fd = -1;

J
Jiri Denemark 已提交
2022
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SAVED);
2023
    event = virDomainEventLifecycleNewFromObj(privdom,
2024 2025
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
2026

2027 2028
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
2029

2030
    ret = 0;
2031
 cleanup:
2032 2033 2034 2035 2036 2037
    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) {
2038
        VIR_FORCE_CLOSE(fd);
2039 2040
        unlink(path);
    }
2041
    virDomainObjEndAPI(&privdom);
2042
    testObjectEventQueue(privconn, event);
2043
    return ret;
2044 2045
}

2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057
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)
2058
{
2059
    testDriverPtr privconn = conn->privateData;
2060
    char *xml = NULL;
2061
    char magic[15];
2062 2063 2064
    int fd = -1;
    int len;
    virDomainDefPtr def = NULL;
2065
    virDomainObjPtr dom = NULL;
2066
    virObjectEventPtr event = NULL;
2067
    int ret = -1;
2068

2069 2070
    virCheckFlags(0, -1);
    if (dxml) {
2071 2072
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
2073 2074 2075
        return -1;
    }

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

2113
    def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
2114
                                  VIR_DOMAIN_DEF_PARSE_INACTIVE);
2115
    if (!def)
2116
        goto cleanup;
2117

2118
    if (testDomainGenerateIfnames(def) < 0)
2119
        goto cleanup;
2120
    if (!(dom = virDomainObjListAdd(privconn->domains,
2121
                                    def,
2122
                                    privconn->xmlopt,
2123 2124 2125
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
2126 2127
        goto cleanup;
    def = NULL;
2128

2129
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_RESTORED) < 0)
2130 2131
        goto cleanup;

2132
    event = virDomainEventLifecycleNewFromObj(dom,
2133 2134
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
2135
    ret = 0;
2136

2137
 cleanup:
2138 2139
    virDomainDefFree(def);
    VIR_FREE(xml);
2140
    VIR_FORCE_CLOSE(fd);
2141
    if (dom)
2142
        virObjectUnlock(dom);
2143
    testObjectEventQueue(privconn, event);
2144
    return ret;
2145 2146
}

2147 2148 2149 2150 2151 2152 2153
static int
testDomainRestore(virConnectPtr conn,
                  const char *path)
{
    return testDomainRestoreFlags(conn, path, NULL, 0);
}

2154 2155 2156 2157
static int testDomainCoreDumpWithFormat(virDomainPtr domain,
                                        const char *to,
                                        unsigned int dumpformat,
                                        unsigned int flags)
2158
{
2159
    testDriverPtr privconn = domain->conn->privateData;
2160
    int fd = -1;
2161
    virDomainObjPtr privdom;
2162
    virObjectEventPtr event = NULL;
2163
    int ret = -1;
2164

E
Eric Blake 已提交
2165 2166
    virCheckFlags(VIR_DUMP_CRASH, -1);

2167

2168
    if (!(privdom = testDomObjFromDomain(domain)))
2169
        goto cleanup;
2170 2171

    if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
2172
        virReportSystemError(errno,
2173 2174
                             _("domain '%s' coredump: failed to open %s"),
                             domain->name, to);
2175
        goto cleanup;
2176
    }
2177
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
2178
        virReportSystemError(errno,
2179 2180
                             _("domain '%s' coredump: failed to write header to %s"),
                             domain->name, to);
2181
        goto cleanup;
2182
    }
2183
    if (VIR_CLOSE(fd) < 0) {
2184
        virReportSystemError(errno,
2185 2186
                             _("domain '%s' coredump: write failed: %s"),
                             domain->name, to);
2187
        goto cleanup;
2188
    }
2189

2190 2191 2192 2193 2194 2195 2196
    /* 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;
    }

2197
    if (flags & VIR_DUMP_CRASH) {
J
Jiri Denemark 已提交
2198
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_CRASHED);
2199
        event = virDomainEventLifecycleNewFromObj(privdom,
2200 2201
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
2202 2203
        if (!privdom->persistent)
            virDomainObjListRemove(privconn->domains, privdom);
2204
    }
2205

2206
    ret = 0;
2207
 cleanup:
2208
    VIR_FORCE_CLOSE(fd);
2209
    virDomainObjEndAPI(&privdom);
2210
    testObjectEventQueue(privconn, event);
2211
    return ret;
2212 2213
}

2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227

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)
{
2228 2229 2230
    char *ret;

    ignore_value(VIR_STRDUP(ret, "linux"));
2231
    return ret;
2232 2233
}

2234 2235 2236

static unsigned long long
testDomainGetMaxMemory(virDomainPtr domain)
2237
{
2238
    virDomainObjPtr privdom;
2239
    unsigned long long ret = 0;
2240

2241 2242
    if (!(privdom = testDomObjFromDomain(domain)))
        return 0;
2243

2244
    ret = virDomainDefGetMemoryActual(privdom->def);
2245

2246
    virDomainObjEndAPI(&privdom);
2247
    return ret;
2248 2249
}

2250 2251
static int testDomainSetMaxMemory(virDomainPtr domain,
                                  unsigned long memory)
2252
{
2253 2254
    virDomainObjPtr privdom;

2255 2256
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2257 2258

    /* XXX validate not over host memory wrt to other domains */
2259
    virDomainDefSetMemoryInitial(privdom->def, memory);
2260

2261
    virDomainObjEndAPI(&privdom);
2262
    return 0;
2263 2264
}

2265 2266
static int testDomainSetMemory(virDomainPtr domain,
                               unsigned long memory)
2267
{
2268
    virDomainObjPtr privdom;
2269
    int ret = -1;
2270

2271 2272
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2273

2274
    if (memory > virDomainDefGetMemoryActual(privdom->def)) {
2275
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2276
        goto cleanup;
2277
    }
2278

2279
    privdom->def->mem.cur_balloon = memory;
2280 2281
    ret = 0;

2282
 cleanup:
2283
    virDomainObjEndAPI(&privdom);
2284
    return ret;
2285 2286
}

2287 2288
static int
testDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
C
Cole Robinson 已提交
2289
{
2290 2291 2292 2293
    virDomainObjPtr vm;
    virDomainDefPtr def;
    int ret = -1;

2294 2295
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2296 2297
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

2298 2299
    if (!(vm = testDomObjFromDomain(domain)))
        return -1;
2300

2301
    if (!(def = virDomainObjGetOneDef(vm, flags)))
2302
        goto cleanup;
2303

2304 2305
    ret = (flags & VIR_DOMAIN_VCPU_MAXIMUM) ? def->maxvcpus : def->vcpus;

2306
 cleanup:
2307
    virDomainObjEndAPI(&vm);
2308
    return ret;
C
Cole Robinson 已提交
2309 2310
}

2311 2312 2313
static int
testDomainGetMaxVcpus(virDomainPtr domain)
{
2314
    return testDomainGetVcpusFlags(domain, (VIR_DOMAIN_AFFECT_LIVE |
2315 2316 2317 2318 2319 2320 2321
                                            VIR_DOMAIN_VCPU_MAXIMUM));
}

static int
testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
                        unsigned int flags)
{
2322
    virDomainObjPtr privdom = NULL;
2323
    virDomainDefPtr def;
2324
    virDomainDefPtr persistentDef;
C
Cole Robinson 已提交
2325 2326
    int ret = -1, maxvcpus;

2327 2328
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2329 2330
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

2331
    if ((maxvcpus = testConnectGetMaxVcpus(domain->conn, NULL)) < 0)
2332
        return -1;
2333 2334

    if (nrCpus > maxvcpus) {
2335
        virReportError(VIR_ERR_INVALID_ARG,
2336 2337
                       _("requested cpu amount exceeds maximum supported amount "
                         "(%d > %d)"), nrCpus, maxvcpus);
2338 2339
        return -1;
    }
2340

2341 2342
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2343

2344
    if (virDomainObjGetDefs(privdom, flags, &def, &persistentDef) < 0)
C
Cole Robinson 已提交
2345 2346
        goto cleanup;

2347
    if (def && def->maxvcpus < nrCpus) {
2348 2349
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested cpu amount exceeds maximum (%d > %d)"),
2350
                       nrCpus, def->maxvcpus);
2351
        goto cleanup;
2352
    }
2353

2354 2355 2356 2357 2358 2359
    if (persistentDef &&
        !(flags & VIR_DOMAIN_VCPU_MAXIMUM) &&
        persistentDef->maxvcpus < nrCpus) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested cpu amount exceeds maximum (%d > %d)"),
                       nrCpus, persistentDef->maxvcpus);
2360
        goto cleanup;
2361
    }
2362

2363 2364
    if (def)
        def->vcpus = nrCpus;
2365

2366 2367 2368 2369 2370 2371
    if (persistentDef) {
        if (flags & VIR_DOMAIN_VCPU_MAXIMUM) {
            persistentDef->maxvcpus = nrCpus;
            if (nrCpus < persistentDef->vcpus)
                persistentDef->vcpus = nrCpus;
        } else {
2372
            persistentDef->vcpus = nrCpus;
2373
        }
2374
    }
2375

2376 2377
    ret = 0;

2378
 cleanup:
2379
    virDomainObjEndAPI(&privdom);
2380
    return ret;
2381 2382
}

2383
static int
2384
testDomainSetVcpus(virDomainPtr domain, unsigned int nrCpus)
2385
{
2386
    return testDomainSetVcpusFlags(domain, nrCpus, VIR_DOMAIN_AFFECT_LIVE);
2387 2388
}

C
Cole Robinson 已提交
2389 2390 2391 2392 2393 2394
static int testDomainGetVcpus(virDomainPtr domain,
                              virVcpuInfoPtr info,
                              int maxinfo,
                              unsigned char *cpumaps,
                              int maplen)
{
2395
    testDriverPtr privconn = domain->conn->privateData;
C
Cole Robinson 已提交
2396
    virDomainObjPtr privdom;
2397
    virDomainDefPtr def;
2398
    size_t i;
2399
    int maxcpu, hostcpus;
C
Cole Robinson 已提交
2400 2401 2402
    int ret = -1;
    struct timeval tv;
    unsigned long long statbase;
2403
    virBitmapPtr allcpumap = NULL;
C
Cole Robinson 已提交
2404

2405 2406
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
C
Cole Robinson 已提交
2407 2408

    if (!virDomainObjIsActive(privdom)) {
2409
        virReportError(VIR_ERR_OPERATION_INVALID,
2410
                       "%s", _("cannot list vcpus for an inactive domain"));
C
Cole Robinson 已提交
2411 2412 2413
        goto cleanup;
    }

2414
    def = privdom->def;
C
Cole Robinson 已提交
2415 2416

    if (gettimeofday(&tv, NULL) < 0) {
2417
        virReportSystemError(errno,
C
Cole Robinson 已提交
2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428
                             "%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;

2429 2430 2431 2432 2433
    if (!(allcpumap = virBitmapNew(hostcpus)))
        goto cleanup;

    virBitmapSetAll(allcpumap);

C
Cole Robinson 已提交
2434 2435 2436 2437
    /* Clamp to actual number of vcpus */
    if (maxinfo > privdom->def->vcpus)
        maxinfo = privdom->def->vcpus;

2438 2439
    memset(info, 0, sizeof(*info) * maxinfo);
    memset(cpumaps, 0, maxinfo * maplen);
C
Cole Robinson 已提交
2440

2441 2442 2443
    for (i = 0; i < maxinfo; i++) {
        virDomainPinDefPtr pininfo;
        virBitmapPtr bitmap = NULL;
C
Cole Robinson 已提交
2444

2445 2446 2447
        pininfo = virDomainPinFind(def->cputune.vcpupin,
                                   def->cputune.nvcpupin,
                                   i);
C
Cole Robinson 已提交
2448

2449 2450 2451 2452 2453 2454
        if (pininfo && pininfo->cpumask)
            bitmap = pininfo->cpumask;
        else if (def->cpumask)
            bitmap = def->cpumask;
        else
            bitmap = allcpumap;
C
Cole Robinson 已提交
2455

2456 2457
        if (cpumaps)
            virBitmapToDataBuf(bitmap, VIR_GET_CPUMAP(cpumaps, maplen, i), maplen);
C
Cole Robinson 已提交
2458

2459 2460 2461
        info[i].number = i;
        info[i].state = VIR_VCPU_RUNNING;
        info[i].cpu = virBitmapLastSetBit(bitmap);
C
Cole Robinson 已提交
2462

2463 2464
        /* Fake an increasing cpu time value */
        info[i].cpuTime = statbase / 10;
C
Cole Robinson 已提交
2465 2466 2467
    }

    ret = maxinfo;
2468
 cleanup:
2469
    virBitmapFree(allcpumap);
2470
    virDomainObjEndAPI(&privdom);
C
Cole Robinson 已提交
2471 2472 2473
    return ret;
}

C
Cole Robinson 已提交
2474 2475 2476 2477 2478 2479
static int testDomainPinVcpu(virDomainPtr domain,
                             unsigned int vcpu,
                             unsigned char *cpumap,
                             int maplen)
{
    virDomainObjPtr privdom;
2480
    virDomainDefPtr def;
C
Cole Robinson 已提交
2481 2482
    int ret = -1;

2483 2484
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
C
Cole Robinson 已提交
2485

2486 2487
    def = privdom->def;

C
Cole Robinson 已提交
2488
    if (!virDomainObjIsActive(privdom)) {
2489
        virReportError(VIR_ERR_OPERATION_INVALID,
2490
                       "%s", _("cannot pin vcpus on an inactive domain"));
C
Cole Robinson 已提交
2491 2492 2493 2494
        goto cleanup;
    }

    if (vcpu > privdom->def->vcpus) {
2495 2496
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("requested vcpu is higher than allocated vcpus"));
C
Cole Robinson 已提交
2497 2498 2499
        goto cleanup;
    }

2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512
    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 已提交
2513 2514 2515
    }

    ret = 0;
2516
 cleanup:
2517
    virDomainObjEndAPI(&privdom);
C
Cole Robinson 已提交
2518 2519 2520
    return ret;
}

2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 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 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574
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 */
    if (ncpumaps > def->vcpus)
        ncpumaps = def->vcpus;

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

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

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

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

    ret = ncpumaps;

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

2575
static char *testDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
2576
{
2577
    virDomainDefPtr def;
2578
    virDomainObjPtr privdom;
2579 2580
    char *ret = NULL;

2581 2582
    /* Flags checked by virDomainDefFormat */

2583 2584
    if (!(privdom = testDomObjFromDomain(domain)))
        return NULL;
2585

2586 2587
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
2588

2589
    ret = virDomainDefFormat(def, virDomainDefFormatConvertXMLFlags(flags));
2590

2591
    virDomainObjEndAPI(&privdom);
2592
    return ret;
2593
}
2594

2595 2596
static int testConnectNumOfDefinedDomains(virConnectPtr conn)
{
2597
    testDriverPtr privconn = conn->privateData;
2598

2599
    return virDomainObjListNumOfDomains(privconn->domains, false, NULL, NULL);
2600 2601
}

2602 2603
static int testConnectListDefinedDomains(virConnectPtr conn,
                                         char **const names,
2604 2605
                                         int maxnames)
{
2606

2607
    testDriverPtr privconn = conn->privateData;
2608 2609

    memset(names, 0, sizeof(*names)*maxnames);
2610 2611
    return virDomainObjListGetInactiveNames(privconn->domains, names, maxnames,
                                            NULL, NULL);
2612 2613
}

2614 2615 2616
static virDomainPtr testDomainDefineXMLFlags(virConnectPtr conn,
                                             const char *xml,
                                             unsigned int flags)
2617
{
2618
    testDriverPtr privconn = conn->privateData;
2619
    virDomainPtr ret = NULL;
2620
    virDomainDefPtr def;
2621
    virDomainObjPtr dom = NULL;
2622
    virObjectEventPtr event = NULL;
2623
    virDomainDefPtr oldDef = NULL;
2624 2625 2626
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;

    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
2627

2628 2629
    if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE;
2630

2631
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
2632
                                       parse_flags)) == NULL)
2633
        goto cleanup;
2634

2635
    if (testDomainGenerateIfnames(def) < 0)
2636
        goto cleanup;
2637
    if (!(dom = virDomainObjListAdd(privconn->domains,
2638
                                    def,
2639
                                    privconn->xmlopt,
2640 2641
                                    0,
                                    &oldDef)))
2642
        goto cleanup;
2643
    def = NULL;
2644
    dom->persistent = 1;
2645

2646
    event = virDomainEventLifecycleNewFromObj(dom,
2647
                                     VIR_DOMAIN_EVENT_DEFINED,
2648
                                     !oldDef ?
2649 2650
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
2651

2652
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
2653
    if (ret)
2654
        ret->id = dom->def->id;
2655

2656
 cleanup:
2657
    virDomainDefFree(def);
2658
    virDomainDefFree(oldDef);
2659
    if (dom)
2660
        virObjectUnlock(dom);
2661
    testObjectEventQueue(privconn, event);
2662
    return ret;
2663 2664
}

2665 2666 2667 2668 2669 2670
static virDomainPtr
testDomainDefineXML(virConnectPtr conn, const char *xml)
{
    return testDomainDefineXMLFlags(conn, xml, 0);
}

2671 2672 2673 2674 2675
static char *testDomainGetMetadata(virDomainPtr dom,
                                   int type,
                                   const char *uri,
                                   unsigned int flags)
{
2676
    testDriverPtr privconn = dom->conn->privateData;
2677
    virDomainObjPtr privdom;
2678
    char *ret;
2679 2680 2681 2682

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, NULL);

2683 2684
    if (!(privdom = testDomObjFromDomain(dom)))
        return NULL;
2685 2686 2687 2688

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

2689
    virDomainObjEndAPI(&privdom);
2690 2691 2692 2693 2694 2695 2696 2697 2698 2699
    return ret;
}

static int testDomainSetMetadata(virDomainPtr dom,
                                 int type,
                                 const char *metadata,
                                 const char *key,
                                 const char *uri,
                                 unsigned int flags)
{
2700
    testDriverPtr privconn = dom->conn->privateData;
2701
    virDomainObjPtr privdom;
2702
    int ret;
2703 2704 2705 2706

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

2707 2708
    if (!(privdom = testDomObjFromDomain(dom)))
        return -1;
2709 2710 2711

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

2714
    virDomainObjEndAPI(&privdom);
2715 2716 2717 2718
    return ret;
}


2719 2720
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
2721 2722
                                      int startCell, int maxCells)
{
2723
    testDriverPtr privconn = conn->privateData;
2724 2725
    int cell;
    size_t i;
2726
    int ret = -1;
2727

2728
    testDriverLock(privconn);
2729
    if (startCell > privconn->numCells) {
2730 2731
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("Range exceeds available cells"));
2732
        goto cleanup;
2733 2734
    }

2735 2736 2737 2738
    for (cell = startCell, i = 0;
         (cell < privconn->numCells && i < maxCells);
         ++cell, ++i) {
        freemems[i] = privconn->cells[cell].mem;
2739
    }
2740
    ret = i;
2741

2742
 cleanup:
2743
    testDriverUnlock(privconn);
2744
    return ret;
2745 2746 2747
}


2748 2749
static int testDomainCreateWithFlags(virDomainPtr domain, unsigned int flags)
{
2750
    testDriverPtr privconn = domain->conn->privateData;
2751
    virDomainObjPtr privdom;
2752
    virObjectEventPtr event = NULL;
2753
    int ret = -1;
2754

2755 2756
    virCheckFlags(0, -1);

2757
    testDriverLock(privconn);
2758

2759
    if (!(privdom = testDomObjFromDomain(domain)))
2760
        goto cleanup;
2761

J
Jiri Denemark 已提交
2762
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_SHUTOFF) {
2763 2764
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Domain '%s' is already running"), domain->name);
2765
        goto cleanup;
2766 2767
    }

2768
    if (testDomainStartState(privconn, privdom,
J
Jiri Denemark 已提交
2769
                             VIR_DOMAIN_RUNNING_BOOTED) < 0)
2770 2771 2772
        goto cleanup;
    domain->id = privdom->def->id;

2773
    event = virDomainEventLifecycleNewFromObj(privdom,
2774 2775
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
2776
    ret = 0;
2777

2778
 cleanup:
2779
    virDomainObjEndAPI(&privdom);
2780
    testObjectEventQueue(privconn, event);
2781
    testDriverUnlock(privconn);
2782
    return ret;
2783 2784
}

2785 2786
static int testDomainCreate(virDomainPtr domain)
{
2787 2788 2789
    return testDomainCreateWithFlags(domain, 0);
}

2790 2791 2792
static int testDomainUndefineFlags(virDomainPtr domain,
                                   unsigned int flags)
{
2793
    testDriverPtr privconn = domain->conn->privateData;
2794
    virDomainObjPtr privdom;
2795
    virObjectEventPtr event = NULL;
2796
    int nsnapshots;
2797
    int ret = -1;
2798

2799 2800
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
                  VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
2801

2802

2803
    if (!(privdom = testDomObjFromDomain(domain)))
2804
        goto cleanup;
2805

C
Cole Robinson 已提交
2806 2807 2808 2809 2810 2811 2812 2813
    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;
    }

2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831
    /* 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. */
    }

2832
    event = virDomainEventLifecycleNewFromObj(privdom,
2833 2834
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
C
Cole Robinson 已提交
2835 2836
    privdom->hasManagedSave = false;

2837
    if (virDomainObjIsActive(privdom))
2838
        privdom->persistent = 0;
2839 2840
    else
        virDomainObjListRemove(privconn->domains, privdom);
2841

2842
    ret = 0;
2843

2844
 cleanup:
2845
    virDomainObjEndAPI(&privdom);
2846
    testObjectEventQueue(privconn, event);
2847
    return ret;
2848 2849
}

2850 2851 2852 2853 2854
static int testDomainUndefine(virDomainPtr domain)
{
    return testDomainUndefineFlags(domain, 0);
}

2855 2856 2857
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
2858 2859
    virDomainObjPtr privdom;

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

2863
    *autostart = privdom->autostart;
2864

2865
    virDomainObjEndAPI(&privdom);
2866
    return 0;
2867 2868 2869 2870 2871 2872
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
2873 2874
    virDomainObjPtr privdom;

2875 2876
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2877

2878
    privdom->autostart = autostart ? 1 : 0;
2879

2880
    virDomainObjEndAPI(&privdom);
2881
    return 0;
2882
}
2883

2884
static char *testDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED,
2885 2886
                                        int *nparams)
{
2887 2888
    char *type = NULL;

2889 2890 2891
    if (nparams)
        *nparams = 1;

2892
    ignore_value(VIR_STRDUP(type, "fair"));
2893

2894 2895 2896
    return type;
}

2897
static int
2898 2899 2900 2901
testDomainGetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int *nparams,
                                      unsigned int flags)
2902
{
2903
    virDomainObjPtr privdom;
2904
    int ret = -1;
2905

2906 2907
    virCheckFlags(0, -1);

2908 2909
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2910

2911 2912
    if (virTypedParameterAssign(params, VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, 50) < 0)
2913
        goto cleanup;
2914 2915
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
2916 2917

    *nparams = 1;
2918 2919
    ret = 0;

2920
 cleanup:
2921
    virDomainObjEndAPI(&privdom);
2922
    return ret;
2923
}
2924

2925
static int
2926 2927 2928
testDomainGetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int *nparams)
2929
{
2930
    return testDomainGetSchedulerParametersFlags(domain, params, nparams, 0);
2931
}
2932

2933
static int
2934 2935 2936 2937
testDomainSetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int nparams,
                                      unsigned int flags)
2938
{
2939
    virDomainObjPtr privdom;
2940 2941
    int ret = -1;
    size_t i;
2942

2943
    virCheckFlags(0, -1);
2944 2945 2946 2947
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
2948
        return -1;
2949

2950 2951
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2952

2953
    for (i = 0; i < nparams; i++) {
2954 2955 2956
        if (STREQ(params[i].field, VIR_DOMAIN_SCHEDULER_WEIGHT)) {
            /* XXX */
            /*privdom->weight = params[i].value.ui;*/
2957
        }
2958
    }
2959

2960 2961
    ret = 0;

2962
    virDomainObjEndAPI(&privdom);
2963
    return ret;
2964 2965
}

2966
static int
2967 2968 2969
testDomainSetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int nparams)
2970
{
2971
    return testDomainSetSchedulerParametersFlags(domain, params, nparams, 0);
2972 2973
}

2974 2975
static int testDomainBlockStats(virDomainPtr domain,
                                const char *path,
2976
                                virDomainBlockStatsPtr stats)
2977 2978 2979 2980
{
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
2981
    int ret = -1;
2982

2983 2984 2985 2986 2987 2988
    if (!*path) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("summary statistics are not supported yet"));
        return ret;
    }

2989 2990
    if (!(privdom = testDomObjFromDomain(domain)))
        return ret;
2991

2992
    if (virDomainDiskIndexByName(privdom->def, path, false) < 0) {
2993 2994
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path: %s"), path);
2995 2996 2997 2998
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
2999
        virReportSystemError(errno,
3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012
                             "%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;
3013
 error:
3014
    virDomainObjEndAPI(&privdom);
3015 3016 3017 3018 3019
    return ret;
}

static int testDomainInterfaceStats(virDomainPtr domain,
                                    const char *path,
3020
                                    virDomainInterfaceStatsPtr stats)
3021 3022 3023 3024
{
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
3025 3026
    size_t i;
    int found = 0, ret = -1;
3027

3028 3029
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3030

3031
    for (i = 0; i < privdom->def->nnets; i++) {
3032
        if (privdom->def->nets[i]->ifname &&
3033
            STREQ(privdom->def->nets[i]->ifname, path)) {
3034 3035 3036 3037 3038 3039
            found = 1;
            break;
        }
    }

    if (!found) {
3040 3041
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path, '%s' is not a known interface"), path);
3042 3043 3044 3045
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
3046
        virReportSystemError(errno,
3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062
                             "%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;
3063
 error:
3064
    virDomainObjEndAPI(&privdom);
3065 3066 3067
    return ret;
}

3068

3069 3070
static virNetworkPtr testNetworkLookupByUUID(virConnectPtr conn,
                                             const unsigned char *uuid)
3071
{
3072
    testDriverPtr privconn = conn->privateData;
3073
    virNetworkObjPtr net;
3074
    virNetworkPtr ret = NULL;
3075

3076
    net = virNetworkObjFindByUUID(privconn->networks, uuid);
3077
    if (net == NULL) {
3078
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3079
        goto cleanup;
3080 3081
    }

3082 3083
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

3084
 cleanup:
3085
    virNetworkObjEndAPI(&net);
3086
    return ret;
3087
}
3088

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

3096
    net = virNetworkObjFindByName(privconn->networks, name);
3097
    if (net == NULL) {
3098
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3099
        goto cleanup;
3100 3101
    }

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

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


3110 3111
static int testConnectNumOfNetworks(virConnectPtr conn)
{
3112
    testDriverPtr privconn = conn->privateData;
3113
    int numActive;
3114

3115 3116
    numActive = virNetworkObjListNumOfNetworks(privconn->networks,
                                               true, NULL, conn);
3117
    return numActive;
3118 3119
}

3120
static int testConnectListNetworks(virConnectPtr conn, char **const names, int nnames) {
3121
    testDriverPtr privconn = conn->privateData;
3122
    int n;
3123

3124 3125
    n = virNetworkObjListGetNames(privconn->networks,
                                  true, names, nnames, NULL, conn);
3126
    return n;
3127 3128
}

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

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

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

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

3148
static int
3149
testConnectListAllNetworks(virConnectPtr conn,
3150 3151 3152
                           virNetworkPtr **nets,
                           unsigned int flags)
{
3153
    testDriverPtr privconn = conn->privateData;
3154 3155 3156

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

3157
    return virNetworkObjListExport(conn, privconn->networks, nets, NULL, flags);
3158
}
3159 3160 3161

static int testNetworkIsActive(virNetworkPtr net)
{
3162
    testDriverPtr privconn = net->conn->privateData;
3163 3164 3165
    virNetworkObjPtr obj;
    int ret = -1;

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

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

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

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

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


3197 3198
static virNetworkPtr testNetworkCreateXML(virConnectPtr conn, const char *xml)
{
3199
    testDriverPtr privconn = conn->privateData;
3200
    virNetworkDefPtr def;
3201
    virNetworkObjPtr net = NULL;
3202
    virNetworkPtr ret = NULL;
3203
    virObjectEventPtr event = NULL;
3204

3205
    if ((def = virNetworkDefParseString(xml)) == NULL)
3206
        goto cleanup;
3207

3208 3209 3210
    if (!(net = virNetworkAssignDef(privconn->networks, def,
                                    VIR_NETWORK_OBJ_LIST_ADD_LIVE |
                                    VIR_NETWORK_OBJ_LIST_ADD_CHECK_LIVE)))
3211 3212
        goto cleanup;
    def = NULL;
3213
    net->active = 1;
3214

3215
    event = virNetworkEventLifecycleNew(net->def->name, net->def->uuid,
3216 3217
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3218

3219
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3220

3221
 cleanup:
3222
    virNetworkDefFree(def);
3223
    testObjectEventQueue(privconn, event);
3224
    virNetworkObjEndAPI(&net);
3225
    return ret;
3226 3227
}

3228
static
3229
virNetworkPtr testNetworkDefineXML(virConnectPtr conn, const char *xml)
3230
{
3231
    testDriverPtr privconn = conn->privateData;
3232
    virNetworkDefPtr def;
3233
    virNetworkObjPtr net = NULL;
3234
    virNetworkPtr ret = NULL;
3235
    virObjectEventPtr event = NULL;
3236

3237
    if ((def = virNetworkDefParseString(xml)) == NULL)
3238
        goto cleanup;
3239

3240
    if (!(net = virNetworkAssignDef(privconn->networks, def, 0)))
3241 3242
        goto cleanup;
    def = NULL;
3243

3244
    event = virNetworkEventLifecycleNew(net->def->name, net->def->uuid,
3245 3246
                                        VIR_NETWORK_EVENT_DEFINED,
                                        0);
3247

3248
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3249

3250
 cleanup:
3251
    virNetworkDefFree(def);
3252
    testObjectEventQueue(privconn, event);
3253
    virNetworkObjEndAPI(&net);
3254
    return ret;
3255 3256
}

3257 3258
static int testNetworkUndefine(virNetworkPtr network)
{
3259
    testDriverPtr privconn = network->conn->privateData;
3260
    virNetworkObjPtr privnet;
3261
    int ret = -1;
3262
    virObjectEventPtr event = NULL;
3263

3264
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3265 3266

    if (privnet == NULL) {
3267
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3268
        goto cleanup;
3269
    }
3270

D
Daniel P. Berrange 已提交
3271
    if (virNetworkObjIsActive(privnet)) {
3272 3273
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is still running"), network->name);
3274
        goto cleanup;
3275 3276
    }

3277
    event = virNetworkEventLifecycleNew(network->name, network->uuid,
3278 3279
                                        VIR_NETWORK_EVENT_UNDEFINED,
                                        0);
3280

3281
    virNetworkRemoveInactive(privconn->networks, privnet);
3282
    ret = 0;
3283

3284
 cleanup:
3285
    testObjectEventQueue(privconn, event);
3286
    virNetworkObjEndAPI(&privnet);
3287
    return ret;
3288 3289
}

3290 3291 3292 3293 3294 3295 3296 3297
static int
testNetworkUpdate(virNetworkPtr net,
                  unsigned int command,
                  unsigned int section,
                  int parentIndex,
                  const char *xml,
                  unsigned int flags)
{
3298
    testDriverPtr privconn = net->conn->privateData;
3299 3300 3301 3302 3303 3304 3305
    virNetworkObjPtr network = NULL;
    int isActive, ret = -1;

    virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
                  VIR_NETWORK_UPDATE_AFFECT_CONFIG,
                  -1);

3306
    network = virNetworkObjFindByUUID(privconn->networks, net->uuid);
3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330
    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;
3331
 cleanup:
3332
    virNetworkObjEndAPI(&network);
3333 3334 3335
    return ret;
}

3336 3337
static int testNetworkCreate(virNetworkPtr network)
{
3338
    testDriverPtr privconn = network->conn->privateData;
3339
    virNetworkObjPtr privnet;
3340
    int ret = -1;
3341
    virObjectEventPtr event = NULL;
3342

3343
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3344
    if (privnet == NULL) {
3345
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3346
        goto cleanup;
3347
    }
3348

D
Daniel P. Berrange 已提交
3349
    if (virNetworkObjIsActive(privnet)) {
3350 3351
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is already running"), network->name);
3352
        goto cleanup;
3353 3354
    }

3355
    privnet->active = 1;
3356
    event = virNetworkEventLifecycleNew(privnet->def->name, privnet->def->uuid,
3357 3358
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3359
    ret = 0;
3360

3361
 cleanup:
3362
    testObjectEventQueue(privconn, event);
3363
    virNetworkObjEndAPI(&privnet);
3364
    return ret;
3365 3366
}

3367 3368
static int testNetworkDestroy(virNetworkPtr network)
{
3369
    testDriverPtr privconn = network->conn->privateData;
3370
    virNetworkObjPtr privnet;
3371
    int ret = -1;
3372
    virObjectEventPtr event = NULL;
3373

3374
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3375
    if (privnet == NULL) {
3376
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3377
        goto cleanup;
3378
    }
3379

3380
    privnet->active = 0;
3381
    event = virNetworkEventLifecycleNew(privnet->def->name, privnet->def->uuid,
3382 3383
                                        VIR_NETWORK_EVENT_STOPPED,
                                        0);
3384
    if (!privnet->persistent)
3385
        virNetworkRemoveInactive(privconn->networks, privnet);
3386

3387 3388
    ret = 0;

3389
 cleanup:
3390
    testObjectEventQueue(privconn, event);
3391
    virNetworkObjEndAPI(&privnet);
3392
    return ret;
3393 3394
}

3395
static char *testNetworkGetXMLDesc(virNetworkPtr network,
E
Eric Blake 已提交
3396
                                   unsigned int flags)
3397
{
3398
    testDriverPtr privconn = network->conn->privateData;
3399
    virNetworkObjPtr privnet;
3400
    char *ret = NULL;
3401

E
Eric Blake 已提交
3402 3403
    virCheckFlags(0, NULL);

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

3410
    ret = virNetworkDefFormat(privnet->def, flags);
3411

3412
 cleanup:
3413
    virNetworkObjEndAPI(&privnet);
3414
    return ret;
3415 3416 3417
}

static char *testNetworkGetBridgeName(virNetworkPtr network) {
3418
    testDriverPtr privconn = network->conn->privateData;
3419
    char *bridge = NULL;
3420 3421
    virNetworkObjPtr privnet;

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

3428
    if (!(privnet->def->bridge)) {
3429 3430 3431
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("network '%s' does not have a bridge name."),
                       privnet->def->name);
3432 3433 3434
        goto cleanup;
    }

3435
    ignore_value(VIR_STRDUP(bridge, privnet->def->bridge));
3436

3437
 cleanup:
3438
    virNetworkObjEndAPI(&privnet);
3439 3440 3441 3442
    return bridge;
}

static int testNetworkGetAutostart(virNetworkPtr network,
3443 3444
                                   int *autostart)
{
3445
    testDriverPtr privconn = network->conn->privateData;
3446
    virNetworkObjPtr privnet;
3447
    int ret = -1;
3448

3449
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3450
    if (privnet == NULL) {
3451
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3452
        goto cleanup;
3453 3454
    }

3455
    *autostart = privnet->autostart;
3456 3457
    ret = 0;

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

static int testNetworkSetAutostart(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
    privnet->autostart = autostart ? 1 : 0;
3477 3478
    ret = 0;

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

C
Cole Robinson 已提交
3484

L
Laine Stump 已提交
3485 3486 3487 3488 3489
/*
 * Physical host interface routines
 */


3490
static int testConnectNumOfInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3491
{
3492
    testDriverPtr privconn = conn->privateData;
3493 3494
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3495 3496

    testDriverLock(privconn);
3497
    for (i = 0; (i < privconn->ifaces.count); i++) {
L
Laine Stump 已提交
3498
        virInterfaceObjLock(privconn->ifaces.objs[i]);
3499
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i]))
L
Laine Stump 已提交
3500 3501 3502 3503 3504 3505 3506
            count++;
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3507
static int testConnectListInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3508
{
3509
    testDriverPtr privconn = conn->privateData;
3510 3511
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3512 3513 3514

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
3515
    for (i = 0; (i < privconn->ifaces.count) && (n < nnames); i++) {
L
Laine Stump 已提交
3516
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3517
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
3518
            if (VIR_STRDUP(names[n++], privconn->ifaces.objs[i]->def->name) < 0) {
L
Laine Stump 已提交
3519
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
3520
                goto error;
L
Laine Stump 已提交
3521 3522 3523 3524 3525 3526 3527 3528
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

3529
 error:
3530
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3531 3532 3533 3534 3535
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

3536
static int testConnectNumOfDefinedInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3537
{
3538
    testDriverPtr privconn = conn->privateData;
3539 3540
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3541 3542

    testDriverLock(privconn);
3543
    for (i = 0; i < privconn->ifaces.count; i++) {
L
Laine Stump 已提交
3544
        virInterfaceObjLock(privconn->ifaces.objs[i]);
3545
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i]))
L
Laine Stump 已提交
3546 3547 3548 3549 3550 3551 3552
            count++;
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3553
static int testConnectListDefinedInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3554
{
3555
    testDriverPtr privconn = conn->privateData;
3556 3557
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3558 3559 3560

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
3561
    for (i = 0; (i < privconn->ifaces.count) && (n < nnames); i++) {
L
Laine Stump 已提交
3562
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3563
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
3564
            if (VIR_STRDUP(names[n++], privconn->ifaces.objs[i]->def->name) < 0) {
L
Laine Stump 已提交
3565
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
3566
                goto error;
L
Laine Stump 已提交
3567 3568 3569 3570 3571 3572 3573 3574
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

3575
 error:
3576
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3577 3578 3579 3580 3581
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

3582
static virInterfacePtr testInterfaceLookupByName(virConnectPtr conn,
L
Laine Stump 已提交
3583 3584
                                                 const char *name)
{
3585
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3586 3587 3588 3589 3590 3591 3592 3593
    virInterfaceObjPtr iface;
    virInterfacePtr ret = NULL;

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

    if (iface == NULL) {
3594
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3595 3596 3597 3598 3599
        goto cleanup;
    }

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

3600
 cleanup:
L
Laine Stump 已提交
3601 3602 3603 3604 3605
    if (iface)
        virInterfaceObjUnlock(iface);
    return ret;
}

3606
static virInterfacePtr testInterfaceLookupByMACString(virConnectPtr conn,
L
Laine Stump 已提交
3607 3608
                                                      const char *mac)
{
3609
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3610 3611 3612 3613 3614 3615 3616 3617 3618
    virInterfaceObjPtr iface;
    int ifacect;
    virInterfacePtr ret = NULL;

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

    if (ifacect == 0) {
3619
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3620 3621 3622 3623
        goto cleanup;
    }

    if (ifacect > 1) {
3624
        virReportError(VIR_ERR_MULTIPLE_INTERFACES, NULL);
L
Laine Stump 已提交
3625 3626 3627 3628 3629
        goto cleanup;
    }

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

3630
 cleanup:
L
Laine Stump 已提交
3631 3632 3633 3634 3635
    if (iface)
        virInterfaceObjUnlock(iface);
    return ret;
}

3636 3637
static int testInterfaceIsActive(virInterfacePtr iface)
{
3638
    testDriverPtr privconn = iface->conn->privateData;
3639 3640 3641 3642 3643 3644 3645
    virInterfaceObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virInterfaceFindByName(&privconn->ifaces, iface->name);
    testDriverUnlock(privconn);
    if (!obj) {
3646
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
3647 3648 3649 3650
        goto cleanup;
    }
    ret = virInterfaceObjIsActive(obj);

3651
 cleanup:
3652 3653 3654 3655 3656
    if (obj)
        virInterfaceObjUnlock(obj);
    return ret;
}

3657
static int testInterfaceChangeBegin(virConnectPtr conn,
E
Eric Blake 已提交
3658
                                    unsigned int flags)
3659
{
3660
    testDriverPtr privconn = conn->privateData;
3661 3662
    int ret = -1;

E
Eric Blake 已提交
3663 3664
    virCheckFlags(0, -1);

3665 3666
    testDriverLock(privconn);
    if (privconn->transaction_running) {
3667
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3668
                       _("there is another transaction running."));
3669 3670 3671 3672 3673 3674 3675 3676 3677 3678
        goto cleanup;
    }

    privconn->transaction_running = true;

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

    ret = 0;
3679
 cleanup:
3680 3681 3682 3683 3684
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceChangeCommit(virConnectPtr conn,
E
Eric Blake 已提交
3685
                                     unsigned int flags)
3686
{
3687
    testDriverPtr privconn = conn->privateData;
3688 3689
    int ret = -1;

E
Eric Blake 已提交
3690 3691
    virCheckFlags(0, -1);

3692 3693 3694
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3695
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3696 3697
                       _("no transaction running, "
                         "nothing to be committed."));
3698 3699 3700 3701 3702 3703 3704 3705
        goto cleanup;
    }

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

    ret = 0;

3706
 cleanup:
3707 3708 3709 3710 3711 3712
    testDriverUnlock(privconn);

    return ret;
}

static int testInterfaceChangeRollback(virConnectPtr conn,
E
Eric Blake 已提交
3713
                                       unsigned int flags)
3714
{
3715
    testDriverPtr privconn = conn->privateData;
3716 3717
    int ret = -1;

E
Eric Blake 已提交
3718 3719
    virCheckFlags(0, -1);

3720 3721 3722
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3723
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3724 3725
                       _("no transaction running, "
                         "nothing to rollback."));
3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738
        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;

3739
 cleanup:
3740 3741 3742
    testDriverUnlock(privconn);
    return ret;
}
3743

L
Laine Stump 已提交
3744
static char *testInterfaceGetXMLDesc(virInterfacePtr iface,
E
Eric Blake 已提交
3745
                                     unsigned int flags)
L
Laine Stump 已提交
3746
{
3747
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3748 3749 3750
    virInterfaceObjPtr privinterface;
    char *ret = NULL;

E
Eric Blake 已提交
3751 3752
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
3753 3754 3755 3756 3757 3758
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);
    testDriverUnlock(privconn);

    if (privinterface == NULL) {
3759
        virReportError(VIR_ERR_NO_INTERFACE, __FUNCTION__);
L
Laine Stump 已提交
3760 3761 3762
        goto cleanup;
    }

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

3765
 cleanup:
L
Laine Stump 已提交
3766 3767 3768 3769 3770 3771 3772
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    return ret;
}


static virInterfacePtr testInterfaceDefineXML(virConnectPtr conn, const char *xmlStr,
E
Eric Blake 已提交
3773
                                              unsigned int flags)
L
Laine Stump 已提交
3774
{
3775
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3776 3777 3778 3779
    virInterfaceDefPtr def;
    virInterfaceObjPtr iface = NULL;
    virInterfacePtr ret = NULL;

E
Eric Blake 已提交
3780 3781
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
3782
    testDriverLock(privconn);
3783
    if ((def = virInterfaceDefParseString(xmlStr)) == NULL)
L
Laine Stump 已提交
3784 3785
        goto cleanup;

3786
    if ((iface = virInterfaceAssignDef(&privconn->ifaces, def)) == NULL)
L
Laine Stump 已提交
3787 3788 3789 3790 3791
        goto cleanup;
    def = NULL;

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

3792
 cleanup:
L
Laine Stump 已提交
3793 3794 3795 3796 3797 3798 3799 3800 3801
    virInterfaceDefFree(def);
    if (iface)
        virInterfaceObjUnlock(iface);
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceUndefine(virInterfacePtr iface)
{
3802
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3803 3804 3805 3806 3807 3808 3809 3810
    virInterfaceObjPtr privinterface;
    int ret = -1;

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

    if (privinterface == NULL) {
3811
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3812 3813 3814 3815 3816 3817 3818
        goto cleanup;
    }

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

3819
 cleanup:
L
Laine Stump 已提交
3820 3821 3822 3823 3824
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceCreate(virInterfacePtr iface,
E
Eric Blake 已提交
3825
                               unsigned int flags)
L
Laine Stump 已提交
3826
{
3827
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3828 3829 3830
    virInterfaceObjPtr privinterface;
    int ret = -1;

E
Eric Blake 已提交
3831 3832
    virCheckFlags(0, -1);

L
Laine Stump 已提交
3833 3834 3835 3836 3837
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);

    if (privinterface == NULL) {
3838
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3839 3840 3841 3842
        goto cleanup;
    }

    if (privinterface->active != 0) {
3843
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
3844 3845 3846 3847 3848 3849
        goto cleanup;
    }

    privinterface->active = 1;
    ret = 0;

3850
 cleanup:
L
Laine Stump 已提交
3851 3852 3853 3854 3855 3856 3857
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceDestroy(virInterfacePtr iface,
E
Eric Blake 已提交
3858
                                unsigned int flags)
L
Laine Stump 已提交
3859
{
3860
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3861 3862 3863
    virInterfaceObjPtr privinterface;
    int ret = -1;

E
Eric Blake 已提交
3864 3865
    virCheckFlags(0, -1);

L
Laine Stump 已提交
3866 3867 3868 3869 3870
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);

    if (privinterface == NULL) {
3871
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3872 3873 3874 3875
        goto cleanup;
    }

    if (privinterface->active == 0) {
3876
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
3877 3878 3879 3880 3881 3882
        goto cleanup;
    }

    privinterface->active = 0;
    ret = 0;

3883
 cleanup:
L
Laine Stump 已提交
3884 3885 3886 3887 3888 3889 3890 3891
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    testDriverUnlock(privconn);
    return ret;
}



C
Cole Robinson 已提交
3892 3893 3894 3895
/*
 * Storage Driver routines
 */

3896

3897 3898
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool)
{
C
Cole Robinson 已提交
3899 3900 3901 3902 3903

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

3904
    return VIR_STRDUP(pool->configFile, "");
C
Cole Robinson 已提交
3905 3906
}

3907

C
Cole Robinson 已提交
3908 3909
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
3910 3911
                            const unsigned char *uuid)
{
3912
    testDriverPtr privconn = conn->privateData;
3913 3914
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3915

3916
    testDriverLock(privconn);
3917
    pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid);
3918
    testDriverUnlock(privconn);
3919 3920

    if (pool == NULL) {
3921
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
3922
        goto cleanup;
C
Cole Robinson 已提交
3923 3924
    }

3925 3926
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
3927

3928
 cleanup:
3929 3930
    if (pool)
        virStoragePoolObjUnlock(pool);
3931
    return ret;
C
Cole Robinson 已提交
3932 3933 3934 3935
}

static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
3936 3937
                            const char *name)
{
3938
    testDriverPtr privconn = conn->privateData;
3939 3940
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3941

3942
    testDriverLock(privconn);
3943
    pool = virStoragePoolObjFindByName(&privconn->pools, name);
3944
    testDriverUnlock(privconn);
3945 3946

    if (pool == NULL) {
3947
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
3948
        goto cleanup;
C
Cole Robinson 已提交
3949 3950
    }

3951 3952
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
3953

3954
 cleanup:
3955 3956
    if (pool)
        virStoragePoolObjUnlock(pool);
3957
    return ret;
C
Cole Robinson 已提交
3958 3959 3960
}

static virStoragePoolPtr
3961 3962
testStoragePoolLookupByVolume(virStorageVolPtr vol)
{
C
Cole Robinson 已提交
3963 3964 3965 3966
    return testStoragePoolLookupByName(vol->conn, vol->pool);
}

static int
3967 3968
testConnectNumOfStoragePools(virConnectPtr conn)
{
3969
    testDriverPtr privconn = conn->privateData;
3970 3971
    int numActive = 0;
    size_t i;
C
Cole Robinson 已提交
3972

3973
    testDriverLock(privconn);
3974
    for (i = 0; i < privconn->pools.count; i++)
C
Cole Robinson 已提交
3975 3976
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numActive++;
3977
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3978 3979 3980 3981 3982

    return numActive;
}

static int
3983 3984
testConnectListStoragePools(virConnectPtr conn,
                            char **const names,
3985 3986
                            int nnames)
{
3987
    testDriverPtr privconn = conn->privateData;
3988 3989
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
3990

3991
    testDriverLock(privconn);
C
Cole Robinson 已提交
3992
    memset(names, 0, sizeof(*names)*nnames);
3993
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
3994
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3995
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
3996
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
3997
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
3998
            goto error;
3999 4000 4001 4002
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4003 4004 4005

    return n;

4006
 error:
4007
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
4008
        VIR_FREE(names[n]);
4009
    testDriverUnlock(privconn);
4010
    return -1;
C
Cole Robinson 已提交
4011 4012 4013
}

static int
4014 4015
testConnectNumOfDefinedStoragePools(virConnectPtr conn)
{
4016
    testDriverPtr privconn = conn->privateData;
4017 4018
    int numInactive = 0;
    size_t i;
C
Cole Robinson 已提交
4019

4020
    testDriverLock(privconn);
4021
    for (i = 0; i < privconn->pools.count; i++) {
4022
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4023 4024
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numInactive++;
4025 4026 4027
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4028 4029 4030 4031 4032

    return numInactive;
}

static int
4033 4034
testConnectListDefinedStoragePools(virConnectPtr conn,
                                   char **const names,
4035 4036
                                   int nnames)
{
4037
    testDriverPtr privconn = conn->privateData;
4038 4039
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
4040

4041
    testDriverLock(privconn);
C
Cole Robinson 已提交
4042
    memset(names, 0, sizeof(*names)*nnames);
4043
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
4044
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4045
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
4046
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
4047
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
4048
            goto error;
4049 4050 4051 4052
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4053 4054 4055

    return n;

4056
 error:
4057
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
4058
        VIR_FREE(names[n]);
4059
    testDriverUnlock(privconn);
4060
    return -1;
C
Cole Robinson 已提交
4061 4062
}

4063
static int
4064 4065 4066
testConnectListAllStoragePools(virConnectPtr conn,
                               virStoragePoolPtr **pools,
                               unsigned int flags)
4067
{
4068
    testDriverPtr privconn = conn->privateData;
4069 4070 4071 4072 4073
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

    testDriverLock(privconn);
4074 4075
    ret = virStoragePoolObjListExport(conn, privconn->pools, pools,
                                      NULL, flags);
4076 4077 4078 4079
    testDriverUnlock(privconn);

    return ret;
}
C
Cole Robinson 已提交
4080

4081 4082
static int testStoragePoolIsActive(virStoragePoolPtr pool)
{
4083
    testDriverPtr privconn = pool->conn->privateData;
4084 4085 4086 4087 4088 4089 4090
    virStoragePoolObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virStoragePoolObjFindByUUID(&privconn->pools, pool->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
4091
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4092 4093 4094 4095
        goto cleanup;
    }
    ret = virStoragePoolObjIsActive(obj);

4096
 cleanup:
4097 4098 4099 4100 4101 4102 4103
    if (obj)
        virStoragePoolObjUnlock(obj);
    return ret;
}

static int testStoragePoolIsPersistent(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 = obj->configFile ? 1 : 0;

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



C
Cole Robinson 已提交
4125
static int
4126 4127
testStoragePoolCreate(virStoragePoolPtr pool,
                      unsigned int flags)
E
Eric Blake 已提交
4128
{
4129
    testDriverPtr privconn = pool->conn->privateData;
4130
    virStoragePoolObjPtr privpool;
4131
    int ret = -1;
4132

E
Eric Blake 已提交
4133 4134
    virCheckFlags(0, -1);

4135
    testDriverLock(privconn);
4136 4137
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4138
    testDriverUnlock(privconn);
4139 4140

    if (privpool == NULL) {
4141
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4142
        goto cleanup;
4143 4144
    }

4145
    if (virStoragePoolObjIsActive(privpool)) {
4146 4147
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4148 4149
        goto cleanup;
    }
C
Cole Robinson 已提交
4150 4151

    privpool->active = 1;
4152
    ret = 0;
C
Cole Robinson 已提交
4153

4154
 cleanup:
4155 4156
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4157
    return ret;
C
Cole Robinson 已提交
4158 4159 4160
}

static char *
4161 4162 4163 4164
testConnectFindStoragePoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type,
                                  const char *srcSpec,
                                  unsigned int flags)
C
Cole Robinson 已提交
4165
{
4166 4167 4168 4169
    virStoragePoolSourcePtr source = NULL;
    int pool_type;
    char *ret = NULL;

E
Eric Blake 已提交
4170 4171
    virCheckFlags(0, NULL);

4172 4173
    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
4174 4175
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
4176 4177 4178 4179
        goto cleanup;
    }

    if (srcSpec) {
4180
        source = virStoragePoolDefParseSourceString(srcSpec, pool_type);
4181 4182 4183 4184 4185 4186 4187
        if (!source)
            goto cleanup;
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
4188
        ignore_value(VIR_STRDUP(ret, defaultPoolSourcesLogicalXML));
4189 4190 4191
        break;

    case VIR_STORAGE_POOL_NETFS:
4192
        if (!source || !source->hosts[0].name) {
4193 4194
            virReportError(VIR_ERR_INVALID_ARG,
                           "%s", _("hostname must be specified for netfs sources"));
4195 4196 4197
            goto cleanup;
        }

4198 4199
        ignore_value(virAsprintf(&ret, defaultPoolSourcesNetFSXML,
                                 source->hosts[0].name));
4200 4201 4202
        break;

    default:
4203 4204
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source discovery"), type);
4205 4206
    }

4207
 cleanup:
4208 4209
    virStoragePoolSourceFree(source);
    return ret;
C
Cole Robinson 已提交
4210 4211 4212 4213
}


static virStoragePoolPtr
4214 4215 4216
testStoragePoolCreateXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4217
{
4218
    testDriverPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4219
    virStoragePoolDefPtr def;
4220
    virStoragePoolObjPtr pool = NULL;
4221
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4222

E
Eric Blake 已提交
4223 4224
    virCheckFlags(0, NULL);

4225
    testDriverLock(privconn);
4226
    if (!(def = virStoragePoolDefParseString(xml)))
4227
        goto cleanup;
C
Cole Robinson 已提交
4228

4229 4230 4231 4232
    pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid);
    if (!pool)
        pool = virStoragePoolObjFindByName(&privconn->pools, def->name);
    if (pool) {
4233 4234
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("storage pool already exists"));
4235
        goto cleanup;
C
Cole Robinson 已提交
4236 4237
    }

4238
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4239
        goto cleanup;
4240
    def = NULL;
C
Cole Robinson 已提交
4241

4242
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4243
        virStoragePoolObjRemove(&privconn->pools, pool);
4244 4245
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4246 4247 4248
    }
    pool->active = 1;

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

4252
 cleanup:
4253
    virStoragePoolDefFree(def);
4254 4255 4256
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4257
    return ret;
C
Cole Robinson 已提交
4258 4259 4260
}

static virStoragePoolPtr
4261 4262 4263
testStoragePoolDefineXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4264
{
4265
    testDriverPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4266
    virStoragePoolDefPtr def;
4267
    virStoragePoolObjPtr pool = NULL;
4268
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4269

E
Eric Blake 已提交
4270 4271
    virCheckFlags(0, NULL);

4272
    testDriverLock(privconn);
4273
    if (!(def = virStoragePoolDefParseString(xml)))
4274
        goto cleanup;
C
Cole Robinson 已提交
4275 4276 4277 4278 4279

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

4280
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4281 4282
        goto cleanup;
    def = NULL;
C
Cole Robinson 已提交
4283

4284
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4285
        virStoragePoolObjRemove(&privconn->pools, pool);
4286 4287
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4288 4289
    }

4290 4291
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4292

4293
 cleanup:
4294
    virStoragePoolDefFree(def);
4295 4296 4297
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4298
    return ret;
C
Cole Robinson 已提交
4299 4300 4301
}

static int
4302 4303
testStoragePoolUndefine(virStoragePoolPtr pool)
{
4304
    testDriverPtr privconn = pool->conn->privateData;
4305
    virStoragePoolObjPtr privpool;
4306
    int ret = -1;
4307

4308
    testDriverLock(privconn);
4309 4310 4311 4312
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
4313
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4314
        goto cleanup;
4315 4316
    }

4317
    if (virStoragePoolObjIsActive(privpool)) {
4318 4319
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4320 4321
        goto cleanup;
    }
C
Cole Robinson 已提交
4322 4323

    virStoragePoolObjRemove(&privconn->pools, privpool);
4324
    privpool = NULL;
4325
    ret = 0;
C
Cole Robinson 已提交
4326

4327
 cleanup:
4328 4329 4330
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
4331
    return ret;
C
Cole Robinson 已提交
4332 4333 4334
}

static int
4335
testStoragePoolBuild(virStoragePoolPtr pool,
E
Eric Blake 已提交
4336 4337
                     unsigned int flags)
{
4338
    testDriverPtr privconn = pool->conn->privateData;
4339
    virStoragePoolObjPtr privpool;
4340
    int ret = -1;
4341

E
Eric Blake 已提交
4342 4343
    virCheckFlags(0, -1);

4344
    testDriverLock(privconn);
4345 4346
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4347
    testDriverUnlock(privconn);
4348 4349

    if (privpool == NULL) {
4350
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4351
        goto cleanup;
4352 4353
    }

4354
    if (virStoragePoolObjIsActive(privpool)) {
4355 4356
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4357 4358
        goto cleanup;
    }
4359
    ret = 0;
C
Cole Robinson 已提交
4360

4361
 cleanup:
4362 4363
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4364
    return ret;
C
Cole Robinson 已提交
4365 4366 4367 4368
}


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

4375
    testDriverLock(privconn);
4376 4377 4378 4379
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
4380
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4381
        goto cleanup;
4382 4383 4384
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4385 4386
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4387
        goto cleanup;
4388
    }
C
Cole Robinson 已提交
4389 4390 4391

    privpool->active = 0;

4392
    if (privpool->configFile == NULL) {
C
Cole Robinson 已提交
4393
        virStoragePoolObjRemove(&privconn->pools, privpool);
4394 4395
        privpool = NULL;
    }
4396
    ret = 0;
C
Cole Robinson 已提交
4397

4398
 cleanup:
4399 4400 4401
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
4402
    return ret;
C
Cole Robinson 已提交
4403 4404 4405 4406
}


static int
4407
testStoragePoolDelete(virStoragePoolPtr pool,
E
Eric Blake 已提交
4408 4409
                      unsigned int flags)
{
4410
    testDriverPtr privconn = pool->conn->privateData;
4411
    virStoragePoolObjPtr privpool;
4412
    int ret = -1;
4413

E
Eric Blake 已提交
4414 4415
    virCheckFlags(0, -1);

4416
    testDriverLock(privconn);
4417 4418
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4419
    testDriverUnlock(privconn);
4420 4421

    if (privpool == NULL) {
4422
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4423 4424 4425 4426
        goto cleanup;
    }

    if (virStoragePoolObjIsActive(privpool)) {
4427 4428
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4429
        goto cleanup;
4430 4431
    }

4432
    ret = 0;
C
Cole Robinson 已提交
4433

4434
 cleanup:
4435 4436
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4437
    return ret;
C
Cole Robinson 已提交
4438 4439 4440 4441
}


static int
4442
testStoragePoolRefresh(virStoragePoolPtr pool,
E
Eric Blake 已提交
4443 4444
                       unsigned int flags)
{
4445
    testDriverPtr privconn = pool->conn->privateData;
4446
    virStoragePoolObjPtr privpool;
4447
    int ret = -1;
4448

E
Eric Blake 已提交
4449 4450
    virCheckFlags(0, -1);

4451
    testDriverLock(privconn);
4452 4453
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4454
    testDriverUnlock(privconn);
4455 4456

    if (privpool == NULL) {
4457
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4458
        goto cleanup;
4459 4460 4461
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4462 4463
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4464
        goto cleanup;
4465
    }
4466
    ret = 0;
C
Cole Robinson 已提交
4467

4468
 cleanup:
4469 4470
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4471
    return ret;
C
Cole Robinson 已提交
4472 4473 4474 4475
}


static int
4476
testStoragePoolGetInfo(virStoragePoolPtr pool,
4477 4478
                       virStoragePoolInfoPtr info)
{
4479
    testDriverPtr privconn = pool->conn->privateData;
4480
    virStoragePoolObjPtr privpool;
4481
    int ret = -1;
4482

4483
    testDriverLock(privconn);
4484 4485
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4486
    testDriverUnlock(privconn);
4487 4488

    if (privpool == NULL) {
4489
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4490
        goto cleanup;
4491
    }
C
Cole Robinson 已提交
4492 4493 4494 4495 4496 4497 4498 4499 4500

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

4503
 cleanup:
4504 4505
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4506
    return ret;
C
Cole Robinson 已提交
4507 4508 4509
}

static char *
4510
testStoragePoolGetXMLDesc(virStoragePoolPtr pool,
E
Eric Blake 已提交
4511 4512
                          unsigned int flags)
{
4513
    testDriverPtr privconn = pool->conn->privateData;
4514
    virStoragePoolObjPtr privpool;
4515
    char *ret = NULL;
4516

E
Eric Blake 已提交
4517 4518
    virCheckFlags(0, NULL);

4519
    testDriverLock(privconn);
4520 4521
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4522
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4523

4524
    if (privpool == NULL) {
4525
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4526
        goto cleanup;
4527 4528
    }

4529
    ret = virStoragePoolDefFormat(privpool->def);
4530

4531
 cleanup:
4532 4533
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4534
    return ret;
C
Cole Robinson 已提交
4535 4536 4537
}

static int
4538
testStoragePoolGetAutostart(virStoragePoolPtr pool,
4539 4540
                            int *autostart)
{
4541
    testDriverPtr privconn = pool->conn->privateData;
4542
    virStoragePoolObjPtr privpool;
4543
    int ret = -1;
4544

4545
    testDriverLock(privconn);
4546 4547
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4548
    testDriverUnlock(privconn);
4549 4550

    if (privpool == NULL) {
4551
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4552
        goto cleanup;
4553
    }
C
Cole Robinson 已提交
4554 4555 4556 4557 4558 4559

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

4562
 cleanup:
4563 4564
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4565
    return ret;
C
Cole Robinson 已提交
4566 4567 4568
}

static int
4569
testStoragePoolSetAutostart(virStoragePoolPtr pool,
4570 4571
                            int autostart)
{
4572
    testDriverPtr privconn = pool->conn->privateData;
4573
    virStoragePoolObjPtr privpool;
4574
    int ret = -1;
4575

4576
    testDriverLock(privconn);
4577 4578
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4579
    testDriverUnlock(privconn);
4580 4581

    if (privpool == NULL) {
4582
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4583
        goto cleanup;
4584
    }
C
Cole Robinson 已提交
4585 4586

    if (!privpool->configFile) {
4587 4588
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("pool has no config file"));
4589
        goto cleanup;
C
Cole Robinson 已提交
4590 4591 4592 4593
    }

    autostart = (autostart != 0);
    privpool->autostart = autostart;
4594 4595
    ret = 0;

4596
 cleanup:
4597 4598
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4599
    return ret;
C
Cole Robinson 已提交
4600 4601 4602 4603
}


static int
4604 4605
testStoragePoolNumOfVolumes(virStoragePoolPtr pool)
{
4606
    testDriverPtr privconn = pool->conn->privateData;
4607
    virStoragePoolObjPtr privpool;
4608
    int ret = -1;
4609

4610
    testDriverLock(privconn);
4611 4612
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4613
    testDriverUnlock(privconn);
4614 4615

    if (privpool == NULL) {
4616
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4617
        goto cleanup;
4618 4619 4620
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4621 4622
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4623
        goto cleanup;
4624
    }
C
Cole Robinson 已提交
4625

4626 4627
    ret = privpool->volumes.count;

4628
 cleanup:
4629 4630
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4631
    return ret;
C
Cole Robinson 已提交
4632 4633 4634
}

static int
4635
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4636
                           char **const names,
4637 4638
                           int maxnames)
{
4639
    testDriverPtr privconn = pool->conn->privateData;
4640
    virStoragePoolObjPtr privpool;
4641 4642
    size_t i = 0;
    int n = 0;
C
Cole Robinson 已提交
4643

4644
    memset(names, 0, maxnames * sizeof(*names));
4645 4646

    testDriverLock(privconn);
4647 4648
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4649
    testDriverUnlock(privconn);
4650 4651

    if (privpool == NULL) {
4652
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4653
        goto cleanup;
4654 4655 4656 4657
    }


    if (!virStoragePoolObjIsActive(privpool)) {
4658 4659
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4660
        goto cleanup;
4661 4662
    }

4663
    for (i = 0; i < privpool->volumes.count && n < maxnames; i++) {
4664
        if (VIR_STRDUP(names[n++], privpool->volumes.objs[i]->name) < 0)
C
Cole Robinson 已提交
4665 4666 4667
            goto cleanup;
    }

4668
    virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4669 4670 4671
    return n;

 cleanup:
4672
    for (n = 0; n < maxnames; n++)
C
Cole Robinson 已提交
4673 4674
        VIR_FREE(names[i]);

4675
    memset(names, 0, maxnames * sizeof(*names));
4676 4677
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4678 4679 4680
    return -1;
}

4681 4682 4683
static int
testStoragePoolListAllVolumes(virStoragePoolPtr obj,
                              virStorageVolPtr **vols,
4684 4685
                              unsigned int flags)
{
4686
    testDriverPtr privconn = obj->conn->privateData;
4687
    virStoragePoolObjPtr pool;
4688
    size_t i;
4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717
    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;
    }

4718
    if (VIR_ALLOC_N(tmp_vols, pool->volumes.count + 1) < 0)
4719 4720
         goto cleanup;

4721
    for (i = 0; i < pool->volumes.count; i++) {
4722 4723
        if (!(vol = virGetStorageVol(obj->conn, pool->def->name,
                                     pool->volumes.objs[i]->name,
4724 4725
                                     pool->volumes.objs[i]->key,
                                     NULL, NULL)))
4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739
            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]);
        }
4740
        VIR_FREE(tmp_vols);
4741 4742 4743 4744 4745 4746 4747
    }

    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
C
Cole Robinson 已提交
4748 4749

static virStorageVolPtr
4750
testStorageVolLookupByName(virStoragePoolPtr pool,
4751 4752
                           const char *name ATTRIBUTE_UNUSED)
{
4753
    testDriverPtr privconn = pool->conn->privateData;
4754 4755
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
4756
    virStorageVolPtr ret = NULL;
4757

4758
    testDriverLock(privconn);
4759 4760
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4761
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4762

4763
    if (privpool == NULL) {
4764
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4765
        goto cleanup;
4766 4767 4768 4769
    }


    if (!virStoragePoolObjIsActive(privpool)) {
4770 4771
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4772
        goto cleanup;
4773 4774 4775 4776 4777
    }

    privvol = virStorageVolDefFindByName(privpool, name);

    if (!privvol) {
4778 4779
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"), name);
4780
        goto cleanup;
C
Cole Robinson 已提交
4781 4782
    }

4783
    ret = virGetStorageVol(pool->conn, privpool->def->name,
4784 4785
                           privvol->name, privvol->key,
                           NULL, NULL);
4786

4787
 cleanup:
4788 4789
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4790
    return ret;
C
Cole Robinson 已提交
4791 4792 4793 4794
}


static virStorageVolPtr
4795
testStorageVolLookupByKey(virConnectPtr conn,
4796 4797
                          const char *key)
{
4798
    testDriverPtr privconn = conn->privateData;
4799
    size_t i;
4800
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4801

4802
    testDriverLock(privconn);
4803
    for (i = 0; i < privconn->pools.count; i++) {
4804
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4805
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4806
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4807 4808
                virStorageVolDefFindByKey(privconn->pools.objs[i], key);

4809 4810 4811 4812
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
4813 4814
                                       privvol->key,
                                       NULL, NULL);
4815
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
4816 4817
                break;
            }
C
Cole Robinson 已提交
4818
        }
4819
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4820
    }
4821
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4822

4823
    if (!ret)
4824 4825
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching key '%s'"), key);
4826 4827

    return ret;
C
Cole Robinson 已提交
4828 4829 4830
}

static virStorageVolPtr
4831
testStorageVolLookupByPath(virConnectPtr conn,
4832 4833
                           const char *path)
{
4834
    testDriverPtr privconn = conn->privateData;
4835
    size_t i;
4836
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4837

4838
    testDriverLock(privconn);
4839
    for (i = 0; i < privconn->pools.count; i++) {
4840
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4841
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4842
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4843 4844
                virStorageVolDefFindByPath(privconn->pools.objs[i], path);

4845 4846 4847 4848
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
4849 4850
                                       privvol->key,
                                       NULL, NULL);
4851
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
4852 4853
                break;
            }
C
Cole Robinson 已提交
4854
        }
4855
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4856
    }
4857
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4858

4859
    if (!ret)
4860 4861
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching path '%s'"), path);
4862 4863

    return ret;
C
Cole Robinson 已提交
4864 4865 4866
}

static virStorageVolPtr
4867 4868 4869
testStorageVolCreateXML(virStoragePoolPtr pool,
                        const char *xmldesc,
                        unsigned int flags)
E
Eric Blake 已提交
4870
{
4871
    testDriverPtr privconn = pool->conn->privateData;
4872
    virStoragePoolObjPtr privpool;
4873 4874
    virStorageVolDefPtr privvol = NULL;
    virStorageVolPtr ret = NULL;
4875

E
Eric Blake 已提交
4876 4877
    virCheckFlags(0, NULL);

4878
    testDriverLock(privconn);
4879 4880
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4881
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4882

4883
    if (privpool == NULL) {
4884
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4885
        goto cleanup;
4886 4887 4888
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4889 4890
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4891
        goto cleanup;
4892
    }
C
Cole Robinson 已提交
4893

4894
    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
4895
    if (privvol == NULL)
4896
        goto cleanup;
4897 4898

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
4899 4900
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
4901
        goto cleanup;
C
Cole Robinson 已提交
4902 4903 4904
    }

    /* Make sure enough space */
4905
    if ((privpool->def->allocation + privvol->target.allocation) >
C
Cole Robinson 已提交
4906
         privpool->def->capacity) {
4907 4908 4909
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
4910
        goto cleanup;
C
Cole Robinson 已提交
4911 4912
    }

4913 4914
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
4915
                    privvol->name) == -1)
4916
        goto cleanup;
C
Cole Robinson 已提交
4917

4918 4919 4920
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
        VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
                                privpool->volumes.count, privvol) < 0)
4921
        goto cleanup;
C
Cole Robinson 已提交
4922

4923
    privpool->def->allocation += privvol->target.allocation;
C
Cole Robinson 已提交
4924 4925 4926
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

4927
    ret = virGetStorageVol(pool->conn, privpool->def->name,
4928 4929
                           privvol->name, privvol->key,
                           NULL, NULL);
4930
    privvol = NULL;
4931

4932
 cleanup:
4933
    virStorageVolDefFree(privvol);
4934 4935
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4936
    return ret;
C
Cole Robinson 已提交
4937 4938
}

4939
static virStorageVolPtr
4940 4941 4942 4943
testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
                            const char *xmldesc,
                            virStorageVolPtr clonevol,
                            unsigned int flags)
E
Eric Blake 已提交
4944
{
4945
    testDriverPtr privconn = pool->conn->privateData;
4946 4947 4948 4949
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol = NULL, origvol = NULL;
    virStorageVolPtr ret = NULL;

E
Eric Blake 已提交
4950 4951
    virCheckFlags(0, NULL);

4952 4953 4954 4955 4956 4957
    testDriverLock(privconn);
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
    testDriverUnlock(privconn);

    if (privpool == NULL) {
4958
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4959 4960 4961 4962
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4963 4964
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4965 4966 4967
        goto cleanup;
    }

4968
    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
4969 4970 4971 4972
    if (privvol == NULL)
        goto cleanup;

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
4973 4974
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
4975 4976 4977 4978 4979
        goto cleanup;
    }

    origvol = virStorageVolDefFindByName(privpool, clonevol->name);
    if (!origvol) {
4980 4981 4982
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       clonevol->name);
4983 4984 4985 4986
        goto cleanup;
    }

    /* Make sure enough space */
4987
    if ((privpool->def->allocation + privvol->target.allocation) >
4988
         privpool->def->capacity) {
4989 4990 4991
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
4992 4993 4994 4995 4996
        goto cleanup;
    }
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

4997 4998
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
4999
                    privvol->name) == -1)
5000 5001
        goto cleanup;

5002 5003 5004
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
        VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
                                privpool->volumes.count, privvol) < 0)
5005 5006
        goto cleanup;

5007
    privpool->def->allocation += privvol->target.allocation;
5008 5009 5010 5011
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    ret = virGetStorageVol(pool->conn, privpool->def->name,
5012 5013
                           privvol->name, privvol->key,
                           NULL, NULL);
5014 5015
    privvol = NULL;

5016
 cleanup:
5017 5018 5019 5020 5021 5022
    virStorageVolDefFree(privvol);
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    return ret;
}

C
Cole Robinson 已提交
5023
static int
5024 5025
testStorageVolDelete(virStorageVolPtr vol,
                     unsigned int flags)
E
Eric Blake 已提交
5026
{
5027
    testDriverPtr privconn = vol->conn->privateData;
5028 5029
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5030
    size_t i;
5031
    int ret = -1;
C
Cole Robinson 已提交
5032

E
Eric Blake 已提交
5033 5034
    virCheckFlags(0, -1);

5035
    testDriverLock(privconn);
5036 5037
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5038
    testDriverUnlock(privconn);
5039 5040

    if (privpool == NULL) {
5041
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5042
        goto cleanup;
5043 5044 5045 5046 5047 5048
    }


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

    if (privvol == NULL) {
5049 5050 5051
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5052
        goto cleanup;
5053 5054 5055
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5056 5057
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5058
        goto cleanup;
5059 5060 5061
    }


5062
    privpool->def->allocation -= privvol->target.allocation;
C
Cole Robinson 已提交
5063 5064 5065
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

5066
    for (i = 0; i < privpool->volumes.count; i++) {
C
Cole Robinson 已提交
5067 5068 5069
        if (privpool->volumes.objs[i] == privvol) {
            virStorageVolDefFree(privvol);

5070
            VIR_DELETE_ELEMENT(privpool->volumes.objs, i, privpool->volumes.count);
C
Cole Robinson 已提交
5071 5072 5073
            break;
        }
    }
5074
    ret = 0;
C
Cole Robinson 已提交
5075

5076
 cleanup:
5077 5078
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5079
    return ret;
C
Cole Robinson 已提交
5080 5081 5082
}


5083 5084
static int testStorageVolumeTypeForPool(int pooltype)
{
C
Cole Robinson 已提交
5085

5086
    switch (pooltype) {
C
Cole Robinson 已提交
5087 5088 5089 5090 5091 5092 5093 5094 5095 5096
        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
5097
testStorageVolGetInfo(virStorageVolPtr vol,
5098 5099
                      virStorageVolInfoPtr info)
{
5100
    testDriverPtr privconn = vol->conn->privateData;
5101 5102
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5103
    int ret = -1;
5104

5105
    testDriverLock(privconn);
5106 5107
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5108
    testDriverUnlock(privconn);
5109 5110

    if (privpool == NULL) {
5111
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5112
        goto cleanup;
5113 5114 5115 5116 5117
    }

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

    if (privvol == NULL) {
5118 5119 5120
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5121
        goto cleanup;
5122 5123 5124
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5125 5126
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5127
        goto cleanup;
5128
    }
C
Cole Robinson 已提交
5129 5130 5131

    memset(info, 0, sizeof(*info));
    info->type = testStorageVolumeTypeForPool(privpool->def->type);
5132 5133
    info->capacity = privvol->target.capacity;
    info->allocation = privvol->target.allocation;
5134
    ret = 0;
C
Cole Robinson 已提交
5135

5136
 cleanup:
5137 5138
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5139
    return ret;
C
Cole Robinson 已提交
5140 5141 5142
}

static char *
5143 5144
testStorageVolGetXMLDesc(virStorageVolPtr vol,
                         unsigned int flags)
E
Eric Blake 已提交
5145
{
5146
    testDriverPtr privconn = vol->conn->privateData;
5147 5148
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5149
    char *ret = NULL;
5150

E
Eric Blake 已提交
5151 5152
    virCheckFlags(0, NULL);

5153
    testDriverLock(privconn);
5154 5155
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5156
    testDriverUnlock(privconn);
5157 5158

    if (privpool == NULL) {
5159
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5160
        goto cleanup;
5161 5162 5163 5164 5165
    }

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

    if (privvol == NULL) {
5166 5167 5168
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5169
        goto cleanup;
5170
    }
C
Cole Robinson 已提交
5171

5172
    if (!virStoragePoolObjIsActive(privpool)) {
5173 5174
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5175
        goto cleanup;
5176 5177
    }

5178
    ret = virStorageVolDefFormat(privpool->def, privvol);
5179

5180
 cleanup:
5181 5182
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5183
    return ret;
C
Cole Robinson 已提交
5184 5185 5186
}

static char *
5187 5188
testStorageVolGetPath(virStorageVolPtr vol)
{
5189
    testDriverPtr privconn = vol->conn->privateData;
5190 5191
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5192
    char *ret = NULL;
5193

5194
    testDriverLock(privconn);
5195 5196
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5197
    testDriverUnlock(privconn);
5198 5199

    if (privpool == NULL) {
5200
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5201
        goto cleanup;
5202 5203 5204 5205 5206
    }

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

    if (privvol == NULL) {
5207 5208 5209
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5210
        goto cleanup;
5211 5212 5213
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5214 5215
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5216
        goto cleanup;
5217 5218
    }

5219
    ignore_value(VIR_STRDUP(ret, privvol->target.path));
5220

5221
 cleanup:
5222 5223
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
5224 5225 5226
    return ret;
}

5227

5228
/* Node device implementations */
5229

5230 5231 5232
static int
testNodeNumOfDevices(virConnectPtr conn,
                     const char *cap,
E
Eric Blake 已提交
5233
                     unsigned int flags)
5234
{
5235
    testDriverPtr driver = conn->privateData;
5236
    int ndevs = 0;
5237
    size_t i;
5238

E
Eric Blake 已提交
5239 5240
    virCheckFlags(0, -1);

5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255
    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 已提交
5256
                    unsigned int flags)
5257
{
5258
    testDriverPtr driver = conn->privateData;
5259
    int ndevs = 0;
5260
    size_t i;
5261

E
Eric Blake 已提交
5262 5263
    virCheckFlags(0, -1);

5264 5265 5266 5267 5268
    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)) {
5269
            if (VIR_STRDUP(names[ndevs++], driver->devs.objs[i]->def->name) < 0) {
5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290
                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)
{
5291
    testDriverPtr driver = conn->privateData;
5292 5293 5294 5295 5296 5297 5298 5299
    virNodeDeviceObjPtr obj;
    virNodeDevicePtr ret = NULL;

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

    if (!obj) {
5300 5301 5302
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       name);
5303 5304 5305 5306 5307
        goto cleanup;
    }

    ret = virGetNodeDevice(conn, name);

5308
 cleanup:
5309 5310 5311 5312 5313 5314
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

static char *
5315
testNodeDeviceGetXMLDesc(virNodeDevicePtr dev,
E
Eric Blake 已提交
5316
                         unsigned int flags)
5317
{
5318
    testDriverPtr driver = dev->conn->privateData;
5319 5320 5321
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

E
Eric Blake 已提交
5322 5323
    virCheckFlags(0, NULL);

5324 5325 5326 5327 5328
    testDriverLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
    testDriverUnlock(driver);

    if (!obj) {
5329 5330 5331
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5332 5333 5334
        goto cleanup;
    }

5335
    ret = virNodeDeviceDefFormat(obj->def);
5336

5337
 cleanup:
5338 5339 5340 5341 5342 5343 5344 5345
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

static char *
testNodeDeviceGetParent(virNodeDevicePtr dev)
{
5346
    testDriverPtr driver = dev->conn->privateData;
5347 5348 5349 5350 5351 5352 5353 5354
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

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

    if (!obj) {
5355 5356 5357
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5358 5359 5360 5361
        goto cleanup;
    }

    if (obj->def->parent) {
5362
        ignore_value(VIR_STRDUP(ret, obj->def->parent));
5363
    } else {
5364 5365
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no parent for this device"));
5366 5367
    }

5368
 cleanup:
5369 5370 5371 5372 5373
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

5374

5375 5376 5377
static int
testNodeDeviceNumOfCaps(virNodeDevicePtr dev)
{
5378
    testDriverPtr driver = dev->conn->privateData;
5379 5380 5381 5382 5383 5384 5385 5386 5387 5388
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

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

    if (!obj) {
5389 5390 5391
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5392 5393 5394 5395 5396 5397 5398
        goto cleanup;
    }

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

5399
 cleanup:
5400 5401 5402 5403 5404 5405 5406 5407 5408
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}


static int
testNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
5409
    testDriverPtr driver = dev->conn->privateData;
5410 5411 5412 5413 5414 5415 5416 5417 5418 5419
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

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

    if (!obj) {
5420 5421 5422
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5423 5424 5425 5426
        goto cleanup;
    }

    for (caps = obj->def->caps; caps && ncaps < maxnames; caps = caps->next) {
5427
        if (VIR_STRDUP(names[ncaps++], virNodeDevCapTypeToString(caps->data.type)) < 0)
5428 5429 5430 5431
            goto cleanup;
    }
    ret = ncaps;

5432
 cleanup:
5433 5434 5435 5436 5437 5438 5439 5440 5441 5442
    if (obj)
        virNodeDeviceObjUnlock(obj);
    if (ret == -1) {
        --ncaps;
        while (--ncaps >= 0)
            VIR_FREE(names[ncaps]);
    }
    return ret;
}

5443 5444 5445
static virNodeDevicePtr
testNodeDeviceCreateXML(virConnectPtr conn,
                        const char *xmlDesc,
E
Eric Blake 已提交
5446
                        unsigned int flags)
5447
{
5448
    testDriverPtr driver = conn->privateData;
5449 5450 5451 5452 5453 5454 5455
    virNodeDeviceDefPtr def = NULL;
    virNodeDeviceObjPtr obj = NULL;
    char *wwnn = NULL, *wwpn = NULL;
    int parent_host = -1;
    virNodeDevicePtr dev = NULL;
    virNodeDevCapsDefPtr caps;

E
Eric Blake 已提交
5456 5457
    virCheckFlags(0, NULL);

5458 5459
    testDriverLock(driver);

5460
    def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, NULL);
5461
    if (def == NULL)
5462 5463 5464
        goto cleanup;

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

5468
    if (virNodeDeviceGetParentHost(&driver->devs,
5469 5470 5471 5472 5473 5474 5475 5476 5477
                                   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);
5478
    if (VIR_STRDUP(def->name, wwpn) < 0)
5479 5480
        goto cleanup;

J
John Ferlan 已提交
5481 5482
    /* Fill in a random 'host' and 'unique_id' value,
     * since this would also come from the backend */
5483 5484
    caps = def->caps;
    while (caps) {
5485
        if (caps->data.type != VIR_NODE_DEV_CAP_SCSI_HOST)
5486 5487
            continue;

5488
        caps->data.scsi_host.host = virRandomBits(10);
J
John Ferlan 已提交
5489
        caps->data.scsi_host.unique_id = 2;
5490 5491 5492 5493
        caps = caps->next;
    }


5494
    if (!(obj = virNodeDeviceAssignDef(&driver->devs, def)))
5495 5496 5497 5498 5499
        goto cleanup;
    virNodeDeviceObjUnlock(obj);

    dev = virGetNodeDevice(conn, def->name);
    def = NULL;
5500
 cleanup:
5501
    testDriverUnlock(driver);
5502
    virNodeDeviceDefFree(def);
5503 5504 5505 5506 5507 5508 5509 5510 5511
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return dev;
}

static int
testNodeDeviceDestroy(virNodeDevicePtr dev)
{
    int ret = 0;
5512
    testDriverPtr driver = dev->conn->privateData;
5513 5514 5515 5516 5517 5518 5519 5520 5521
    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) {
5522 5523 5524
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5525 5526 5527
        goto out;
    }

5528
    if (virNodeDeviceGetWWNs(obj->def, &wwnn, &wwpn) == -1)
5529 5530
        goto out;

5531
    if (VIR_STRDUP(parent_name, obj->def->parent) < 0)
5532 5533 5534 5535 5536 5537 5538 5539 5540
        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 */
5541
    if (virNodeDeviceGetParentHost(&driver->devs,
5542 5543 5544 5545 5546 5547 5548 5549 5550 5551
                                   dev->name,
                                   parent_name,
                                   &parent_host) == -1) {
        obj = NULL;
        goto out;
    }

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

5552
 out:
5553 5554 5555 5556 5557 5558 5559 5560
    if (obj)
        virNodeDeviceObjUnlock(obj);
    VIR_FREE(parent_name);
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return ret;
}

5561 5562

/* Domain event implementations */
5563
static int
5564 5565 5566 5567
testConnectDomainEventRegister(virConnectPtr conn,
                               virConnectDomainEventCallback callback,
                               void *opaque,
                               virFreeCallback freecb)
5568
{
5569
    testDriverPtr driver = conn->privateData;
5570
    int ret = 0;
5571

5572
    if (virDomainEventStateRegister(conn, driver->eventState,
5573 5574
                                    callback, opaque, freecb) < 0)
        ret = -1;
5575 5576 5577 5578

    return ret;
}

5579

5580
static int
5581 5582
testConnectDomainEventDeregister(virConnectPtr conn,
                                 virConnectDomainEventCallback callback)
5583
{
5584
    testDriverPtr driver = conn->privateData;
5585
    int ret = 0;
5586

5587
    if (virDomainEventStateDeregister(conn, driver->eventState,
5588 5589
                                      callback) < 0)
        ret = -1;
5590 5591 5592 5593

    return ret;
}

5594 5595

static int
5596 5597 5598 5599 5600 5601
testConnectDomainEventRegisterAny(virConnectPtr conn,
                                  virDomainPtr dom,
                                  int eventID,
                                  virConnectDomainEventGenericCallback callback,
                                  void *opaque,
                                  virFreeCallback freecb)
5602
{
5603
    testDriverPtr driver = conn->privateData;
5604 5605
    int ret;

5606
    if (virDomainEventStateRegisterID(conn, driver->eventState,
5607 5608
                                      dom, eventID,
                                      callback, opaque, freecb, &ret) < 0)
5609
        ret = -1;
5610 5611 5612 5613 5614

    return ret;
}

static int
5615 5616
testConnectDomainEventDeregisterAny(virConnectPtr conn,
                                    int callbackID)
5617
{
5618
    testDriverPtr driver = conn->privateData;
5619
    int ret = 0;
5620

5621
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5622 5623
                                        callbackID) < 0)
        ret = -1;
5624 5625 5626 5627 5628

    return ret;
}


5629 5630 5631 5632 5633 5634 5635 5636
static int
testConnectNetworkEventRegisterAny(virConnectPtr conn,
                                   virNetworkPtr net,
                                   int eventID,
                                   virConnectNetworkEventGenericCallback callback,
                                   void *opaque,
                                   virFreeCallback freecb)
{
5637
    testDriverPtr driver = conn->privateData;
5638 5639
    int ret;

5640
    if (virNetworkEventStateRegisterID(conn, driver->eventState,
5641
                                       net, eventID, callback,
5642 5643 5644 5645 5646 5647 5648 5649 5650 5651
                                       opaque, freecb, &ret) < 0)
        ret = -1;

    return ret;
}

static int
testConnectNetworkEventDeregisterAny(virConnectPtr conn,
                                     int callbackID)
{
5652
    testDriverPtr driver = conn->privateData;
5653
    int ret = 0;
5654

5655
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5656 5657
                                        callbackID) < 0)
        ret = -1;
5658 5659 5660 5661

    return ret;
}

5662 5663 5664
static int testConnectListAllDomains(virConnectPtr conn,
                                     virDomainPtr **domains,
                                     unsigned int flags)
5665
{
5666
    testDriverPtr privconn = conn->privateData;
5667

O
Osier Yang 已提交
5668
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
5669

5670 5671
    return virDomainObjListExport(privconn->domains, conn, domains,
                                  NULL, flags);
5672 5673
}

5674
static int
P
Peter Krempa 已提交
5675
testNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,
5676 5677 5678 5679 5680 5681 5682
                  unsigned char **cpumap,
                  unsigned int *online,
                  unsigned int flags)
{
    virCheckFlags(0, -1);

    if (cpumap) {
5683
        if (VIR_ALLOC_N(*cpumap, 1) < 0)
P
Peter Krempa 已提交
5684
            return -1;
5685 5686 5687 5688 5689 5690
        *cpumap[0] = 0x15;
    }

    if (online)
        *online = 3;

P
Peter Krempa 已提交
5691
    return  8;
5692 5693
}

5694 5695 5696 5697 5698 5699 5700 5701 5702 5703
static char *
testDomainScreenshot(virDomainPtr dom ATTRIBUTE_UNUSED,
                     virStreamPtr st,
                     unsigned int screen ATTRIBUTE_UNUSED,
                     unsigned int flags)
{
    char *ret = NULL;

    virCheckFlags(0, NULL);

5704
    if (VIR_STRDUP(ret, "image/png") < 0)
5705 5706
        return NULL;

5707
    if (virFDStreamOpenFile(st, PKGDATADIR "/libvirtLogo.png", 0, 0, O_RDONLY) < 0)
5708 5709 5710 5711 5712
        VIR_FREE(ret);

    return ret;
}

5713 5714 5715 5716 5717 5718 5719 5720 5721
static int
testConnectGetCPUModelNames(virConnectPtr conn ATTRIBUTE_UNUSED,
                            const char *arch,
                            char ***models,
                            unsigned int flags)
{
    virCheckFlags(0, -1);
    return cpuGetModels(arch, models);
}
5722

C
Cole Robinson 已提交
5723 5724 5725
static int
testDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
5726
    testDriverPtr privconn = dom->conn->privateData;
C
Cole Robinson 已提交
5727
    virDomainObjPtr vm = NULL;
5728
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
5729 5730 5731 5732 5733 5734
    int ret = -1;

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

5735 5736
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750

    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);
5751
    event = virDomainEventLifecycleNewFromObj(vm,
C
Cole Robinson 已提交
5752 5753 5754 5755 5756
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
    vm->hasManagedSave = true;

    ret = 0;
5757
 cleanup:
5758
    virDomainObjEndAPI(&vm);
5759
    testObjectEventQueue(privconn, event);
C
Cole Robinson 已提交
5760 5761 5762 5763 5764 5765 5766 5767 5768

    return ret;
}


static int
testDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm;
5769
    int ret;
C
Cole Robinson 已提交
5770 5771 5772

    virCheckFlags(0, -1);

5773 5774
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5775 5776

    ret = vm->hasManagedSave;
5777

5778
    virDomainObjEndAPI(&vm);
C
Cole Robinson 已提交
5779 5780 5781 5782 5783 5784 5785 5786 5787 5788
    return ret;
}

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

    virCheckFlags(0, -1);

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

    vm->hasManagedSave = false;
5793

5794
    virDomainObjEndAPI(&vm);
5795
    return 0;
C
Cole Robinson 已提交
5796 5797 5798
}


5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832
/*
 * 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;
5833
    int n;
5834 5835 5836 5837 5838

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5839
        return -1;
5840 5841 5842

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

5843
    virDomainObjEndAPI(&vm);
5844 5845 5846 5847 5848 5849 5850 5851 5852 5853
    return n;
}

static int
testDomainSnapshotListNames(virDomainPtr domain,
                            char **names,
                            int nameslen,
                            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 5864

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

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

static int
testDomainListAllSnapshots(virDomainPtr domain,
                           virDomainSnapshotPtr **snaps,
                           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

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

5885
    virDomainObjEndAPI(&vm);
5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902
    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)))
5903
        return -1;
5904 5905 5906 5907 5908 5909 5910

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

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

5911
 cleanup:
5912
    virDomainObjEndAPI(&vm);
5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927
    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)))
5928
        return -1;
5929 5930 5931 5932 5933 5934

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

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

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

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

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

5961
 cleanup:
5962
    virDomainObjEndAPI(&vm);
5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977
    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)))
5978
        return NULL;
5979 5980 5981 5982 5983 5984

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

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

5985
 cleanup:
5986
    virDomainObjEndAPI(&vm);
5987 5988 5989 5990 5991 5992 5993 5994
    return snapshot;
}

static int
testDomainHasCurrentSnapshot(virDomainPtr domain,
                             unsigned int flags)
{
    virDomainObjPtr vm;
5995
    int ret;
5996 5997 5998 5999

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6000
        return -1;
6001 6002 6003

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

6004
    virDomainObjEndAPI(&vm);
6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018
    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)))
6019
        return NULL;
6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032

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

6033
 cleanup:
6034
    virDomainObjEndAPI(&vm);
6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047
    return parent;
}

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

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
6048
        return NULL;
6049 6050 6051 6052 6053 6054 6055 6056 6057

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

6058
 cleanup:
6059
    virDomainObjEndAPI(&vm);
6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074
    return snapshot;
}

static char *
testDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
                             unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    char *xml = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    char uuidstr[VIR_UUID_STRING_BUFLEN];

    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6075
        return NULL;
6076 6077 6078 6079 6080 6081

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

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

6082 6083 6084
    xml = virDomainSnapshotDefFormat(uuidstr, snap->def,
                                     virDomainDefFormatConvertXMLFlags(flags),
                                     0);
6085

6086
 cleanup:
6087
    virDomainObjEndAPI(&vm);
6088 6089 6090 6091 6092 6093 6094 6095
    return xml;
}

static int
testDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6096
    int ret;
6097 6098 6099 6100

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6101
        return -1;
6102 6103 6104 6105

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

6106
    virDomainObjEndAPI(&vm);
6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120
    return ret;
}


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

    virCheckFlags(0, -1);

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

C
Cole Robinson 已提交
6123
    if (!testSnapObjFromSnapshot(vm, snapshot))
6124 6125 6126 6127
        goto cleanup;

    ret = 1;

6128
 cleanup:
6129
    virDomainObjEndAPI(&vm);
6130 6131 6132
    return ret;
}

6133 6134 6135 6136 6137 6138
static int
testDomainSnapshotAlignDisks(virDomainObjPtr vm,
                             virDomainSnapshotDefPtr def,
                             unsigned int flags)
{
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
E
Eric Blake 已提交
6139
    bool align_match = true;
6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167

    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)
{
6168
    testDriverPtr privconn = domain->conn->privateData;
6169 6170 6171 6172
    virDomainObjPtr vm = NULL;
    virDomainSnapshotDefPtr def = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr snapshot = NULL;
6173
    virObjectEventPtr event = NULL;
6174
    char *xml = NULL;
6175 6176
    bool update_current = true;
    bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
6177 6178 6179 6180 6181 6182 6183 6184
    unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;

    /*
     * DISK_ONLY: Not implemented yet
     * REUSE_EXT: Not implemented yet
     *
     * NO_METADATA: Explicitly not implemented
     *
6185
     * REDEFINE + CURRENT: Implemented
6186 6187 6188 6189 6190 6191
     * HALT: Implemented
     * QUIESCE: Nothing to do
     * ATOMIC: Nothing to do
     * LIVE: Nothing to do
     */
    virCheckFlags(
6192 6193
        VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
        VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
6194 6195 6196 6197 6198
        VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
        VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
        VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
        VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, NULL);

6199 6200 6201 6202 6203
    if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)))
        update_current = false;
    if (redefine)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;

6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218
    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;

6219
    if (redefine) {
C
Cole Robinson 已提交
6220 6221
        if (virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
                                          &update_current, flags) < 0)
6222 6223 6224 6225 6226 6227 6228
            goto cleanup;
    } else {
        if (!(def->dom = virDomainDefCopy(vm->def,
                                          privconn->caps,
                                          privconn->xmlopt,
                                          true)))
            goto cleanup;
6229

6230
        if (testDomainSnapshotAlignDisks(vm, def, flags) < 0)
6231 6232 6233
            goto cleanup;
    }

6234 6235 6236 6237
    if (!snap) {
        if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
            goto cleanup;
        def = NULL;
6238 6239
    }

6240 6241 6242 6243 6244 6245 6246 6247 6248 6249
    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);
6250
            event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
6251 6252 6253
                                    VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
        }
    }
6254 6255

    snapshot = virGetDomainSnapshot(domain, snap->def->name);
6256
 cleanup:
6257 6258 6259 6260
    VIR_FREE(xml);
    if (vm) {
        if (snapshot) {
            virDomainSnapshotObjPtr other;
6261 6262
            if (update_current)
                vm->current_snapshot = snap;
6263 6264 6265 6266 6267 6268 6269
            other = virDomainSnapshotFindByName(vm->snapshots,
                                                snap->def->parent);
            snap->parent = other;
            other->nchildren++;
            snap->sibling = other->first_child;
            other->first_child = snap;
        }
6270
        virDomainObjEndAPI(&vm);
6271
    }
6272
    testObjectEventQueue(privconn, event);
6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314
    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;

6315
    if (rep->err < 0)
6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357
        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) {
6358
            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)
6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401
                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;
6402
 cleanup:
6403
    virDomainObjEndAPI(&vm);
6404 6405 6406 6407 6408 6409 6410
    return ret;
}

static int
testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                           unsigned int flags)
{
6411
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6412 6413
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
6414 6415
    virObjectEventPtr event = NULL;
    virObjectEventPtr event2 = NULL;
6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506
    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);
6507
                event = virDomainEventLifecycleNewFromObj(vm,
6508 6509
                            VIR_DOMAIN_EVENT_STOPPED,
                            VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
6510
                testObjectEventQueue(privconn, event);
6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521
                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. */
6522
                event = virDomainEventLifecycleNewFromObj(vm,
6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535
                                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;
6536
            event = virDomainEventLifecycleNewFromObj(vm,
6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549
                                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 */
6550
                event2 = virDomainEventLifecycleNewFromObj(vm,
6551 6552 6553 6554 6555
                                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 已提交
6556
            virObjectUnref(event);
6557 6558 6559 6560
            event = NULL;

            if (was_stopped) {
                /* Transition 2 */
6561
                event = virDomainEventLifecycleNewFromObj(vm,
6562 6563 6564 6565
                                VIR_DOMAIN_EVENT_STARTED,
                                VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            } else if (was_running) {
                /* Transition 8 */
6566
                event = virDomainEventLifecycleNewFromObj(vm,
6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578
                                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);
6579
            event = virDomainEventLifecycleNewFromObj(vm,
6580 6581 6582 6583 6584 6585 6586 6587 6588
                                    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;

6589
            testObjectEventQueue(privconn, event);
6590
            event = virDomainEventLifecycleNewFromObj(vm,
6591 6592 6593
                            VIR_DOMAIN_EVENT_STARTED,
                            VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            if (paused) {
6594
                event2 = virDomainEventLifecycleNewFromObj(vm,
6595 6596 6597 6598 6599 6600 6601 6602
                                VIR_DOMAIN_EVENT_SUSPENDED,
                                VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
            }
        }
    }

    vm->current_snapshot = snap;
    ret = 0;
6603
 cleanup:
6604
    if (event) {
6605
        testObjectEventQueue(privconn, event);
6606
        testObjectEventQueue(privconn, event2);
C
Cole Robinson 已提交
6607
    } else {
C
Cédric Bosdonnat 已提交
6608
        virObjectUnref(event2);
6609
    }
6610
    virDomainObjEndAPI(&vm);
6611 6612 6613 6614 6615

    return ret;
}


6616

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

E
Eric Blake 已提交
6713
    .connectBaselineCPU = testConnectBaselineCPU, /* 1.2.0 */
6714 6715 6716
};

static virNetworkDriver testNetworkDriver = {
6717 6718 6719 6720 6721
    .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 */
6722 6723
    .connectNetworkEventRegisterAny = testConnectNetworkEventRegisterAny, /* 1.2.1 */
    .connectNetworkEventDeregisterAny = testConnectNetworkEventDeregisterAny, /* 1.2.1 */
6724 6725 6726 6727
    .networkLookupByUUID = testNetworkLookupByUUID, /* 0.3.2 */
    .networkLookupByName = testNetworkLookupByName, /* 0.3.2 */
    .networkCreateXML = testNetworkCreateXML, /* 0.3.2 */
    .networkDefineXML = testNetworkDefineXML, /* 0.3.2 */
6728
    .networkUndefine = testNetworkUndefine, /* 0.3.2 */
6729
    .networkUpdate = testNetworkUpdate, /* 0.10.2 */
6730
    .networkCreate = testNetworkCreate, /* 0.3.2 */
6731 6732 6733 6734 6735 6736 6737
    .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 */
6738 6739
};

L
Laine Stump 已提交
6740
static virInterfaceDriver testInterfaceDriver = {
6741 6742 6743 6744 6745 6746
    .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 */
6747 6748 6749 6750 6751 6752
    .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 */
6753 6754 6755
    .interfaceChangeBegin = testInterfaceChangeBegin,   /* 0.9.2 */
    .interfaceChangeCommit = testInterfaceChangeCommit,  /* 0.9.2 */
    .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */
L
Laine Stump 已提交
6756 6757 6758
};


6759
static virStorageDriver testStorageDriver = {
6760 6761 6762 6763 6764 6765
    .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 */
6766 6767 6768
    .storagePoolLookupByName = testStoragePoolLookupByName, /* 0.5.0 */
    .storagePoolLookupByUUID = testStoragePoolLookupByUUID, /* 0.5.0 */
    .storagePoolLookupByVolume = testStoragePoolLookupByVolume, /* 0.5.0 */
6769 6770
    .storagePoolCreateXML = testStoragePoolCreateXML, /* 0.5.0 */
    .storagePoolDefineXML = testStoragePoolDefineXML, /* 0.5.0 */
6771 6772
    .storagePoolBuild = testStoragePoolBuild, /* 0.5.0 */
    .storagePoolUndefine = testStoragePoolUndefine, /* 0.5.0 */
6773
    .storagePoolCreate = testStoragePoolCreate, /* 0.5.0 */
6774 6775 6776 6777 6778 6779 6780
    .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 */
6781
    .storagePoolNumOfVolumes = testStoragePoolNumOfVolumes, /* 0.5.0 */
6782 6783 6784
    .storagePoolListVolumes = testStoragePoolListVolumes, /* 0.5.0 */
    .storagePoolListAllVolumes = testStoragePoolListAllVolumes, /* 0.10.2 */

6785 6786 6787 6788 6789 6790 6791 6792 6793
    .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 */
6794 6795
    .storagePoolIsActive = testStoragePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = testStoragePoolIsPersistent, /* 0.7.3 */
6796 6797
};

6798
static virNodeDeviceDriver testNodeDeviceDriver = {
6799 6800 6801 6802 6803 6804 6805 6806 6807
    .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 */
6808 6809
};

6810 6811 6812 6813 6814 6815 6816 6817
static virConnectDriver testConnectDriver = {
    .hypervisorDriver = &testHypervisorDriver,
    .interfaceDriver = &testInterfaceDriver,
    .networkDriver = &testNetworkDriver,
    .nodeDeviceDriver = &testNodeDeviceDriver,
    .nwfilterDriver = NULL,
    .secretDriver = NULL,
    .storageDriver = &testStorageDriver,
6818 6819
};

6820 6821 6822 6823 6824 6825 6826 6827
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
6828 6829
    return virRegisterConnectDriver(&testConnectDriver,
                                    false);
6830
}