test_driver.c 194.0 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 "storage_event.h"
53
#include "node_device_conf.h"
54
#include "virxml.h"
55
#include "virthread.h"
56
#include "virlog.h"
E
Eric Blake 已提交
57
#include "virfile.h"
58
#include "virtypedparam.h"
59
#include "virrandom.h"
60
#include "virstring.h"
61
#include "cpu/cpu.h"
62
#include "virauth.h"
63
#include "viratomic.h"
64
#include "virdomainobjlist.h"
65

66 67
#define VIR_FROM_THIS VIR_FROM_TEST

68 69
VIR_LOG_INIT("test.test_driver");

70

71 72 73 74 75
#define MAX_CPUS 128

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

#define MAX_CELLS 128
82

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

90
struct _testDriver {
91
    virMutex lock;
92

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

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

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

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

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

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

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

160

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

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

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

    virObjectEventStateQueue(driver->eventState, event);
}

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

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

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

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

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

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

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

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

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

292 293 294
    *data = nsdata;
    return 0;

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

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

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

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

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

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

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


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

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

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

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

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

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

368
    return caps;
369

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

375

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

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

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

    return ret;

 error:
    testDriverFree(ret);
    return NULL;
}


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


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

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

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

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

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

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

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

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

    return vm;
}

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

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

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

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

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

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

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

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

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

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

571
    return 0;
572 573
}

574

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

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

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

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

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

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

617 618 619 620 621 622 623

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

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

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

    conn->privateData = privconn;
648

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

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

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

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

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

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

693
    virObjectUnlock(domobj);
694

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

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

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

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

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

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

739 740
    defaultConn = privconn;

741
    virMutexUnlock(&defaultLock);
742

743 744
    return VIR_DRV_OPEN_SUCCESS;

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1024
        virObjectUnlock(obj);
1025
    }
1026

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        virNodeDeviceObjUnlock(obj);
    }

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

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

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

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

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

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

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

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

1348
    return 0;
1349 1350

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

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

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

1413
static virDrvOpenStatus testConnectOpen(virConnectPtr conn,
1414
                                        virConnectAuthPtr auth,
1415
                                        virConfPtr conf ATTRIBUTE_UNUSED,
1416
                                        unsigned int flags)
1417
{
1418
    int ret;
1419

E
Eric Blake 已提交
1420 1421
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

1422
    if (!conn->uri)
1423
        return VIR_DRV_OPEN_DECLINED;
1424

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

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

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

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

1447 1448 1449
    if (ret != VIR_DRV_OPEN_SUCCESS)
        return ret;

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

1454
    return VIR_DRV_OPEN_SUCCESS;
1455 1456
}

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

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

1471
    testDriverLock(privconn);
1472
    testDriverFree(privconn);
1473 1474 1475

    if (dflt) {
        defaultConn = NULL;
1476
        virMutexUnlock(&defaultLock);
1477 1478
    }

1479
    conn->privateData = NULL;
1480
    return 0;
1481 1482
}

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

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


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

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

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

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

1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531
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;
}

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

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

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

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

1561
    return count;
1562 1563
}

1564 1565 1566
static int testDomainIsActive(virDomainPtr dom)
{
    virDomainObjPtr obj;
1567
    int ret;
1568

1569 1570
    if (!(obj = testDomObjFromDomain(dom)))
        return -1;
1571

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

static int testDomainIsPersistent(virDomainPtr dom)
{
    virDomainObjPtr obj;
1580 1581 1582 1583
    int ret;

    if (!(obj = testDomObjFromDomain(dom)))
        return -1;
1584 1585 1586

    ret = obj->persistent;

1587
    virDomainObjEndAPI(&obj);
1588 1589 1590
    return ret;
}

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

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

1607 1608 1609
    virCheckFlags(VIR_DOMAIN_START_VALIDATE, NULL);

    if (flags & VIR_DOMAIN_START_VALIDATE)
1610
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
1611

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

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

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

1636
    event = virDomainEventLifecycleNewFromObj(dom,
1637 1638 1639
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);

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

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


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

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

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

1670
 cleanup:
1671
    if (dom)
1672
        virObjectUnlock(dom);
1673
    return ret;
1674 1675
}

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

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

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

1692
 cleanup:
1693
    if (dom)
1694
        virObjectUnlock(dom);
1695
    return ret;
1696 1697
}

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

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

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

1714
 cleanup:
1715
    virDomainObjEndAPI(&dom);
1716
    return ret;
1717 1718
}

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

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

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


1737
    if (!(privdom = testDomObjFromDomain(domain)))
1738
        goto cleanup;
1739

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

1745 1746
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
1747 1748

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

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

1762 1763
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1764

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

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

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

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

1792 1793
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1794

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

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

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

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

1822 1823
    virCheckFlags(0, -1);

1824

1825
    if (!(privdom = testDomObjFromDomain(domain)))
1826
        goto cleanup;
1827

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

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

1839 1840
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
1841

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

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

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


1864
    if (!(privdom = testDomObjFromDomain(domain)))
1865
        goto cleanup;
1866

J
Jiri Denemark 已提交
1867 1868 1869
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTDOWN,
                         VIR_DOMAIN_SHUTDOWN_USER);

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

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

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

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

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

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

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

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

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

1921 1922
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1923 1924

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

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

1937
 cleanup:
1938
    virDomainObjEndAPI(&privdom);
1939
    return ret;
1940 1941
}

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

    virCheckFlags(0, -1);

1952 1953
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1954

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

1957
    virDomainObjEndAPI(&privdom);
1958 1959

    return 0;
1960 1961
}

1962 1963
#define TEST_SAVE_MAGIC "TestGuestMagic"

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

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

1983

1984
    if (!(privdom = testDomObjFromDomain(domain)))
1985
        goto cleanup;
1986

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

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

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

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

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

2036 2037
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
2038

2039
    ret = 0;
2040
 cleanup:
2041 2042 2043 2044 2045 2046
    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) {
2047
        VIR_FORCE_CLOSE(fd);
2048 2049
        unlink(path);
    }
2050
    virDomainObjEndAPI(&privdom);
2051
    testObjectEventQueue(privconn, event);
2052
    return ret;
2053 2054
}

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

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

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

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

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

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

2146
    event = virDomainEventLifecycleNewFromObj(dom,
2147 2148
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
2149
    ret = 0;
2150

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

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

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

E
Eric Blake 已提交
2179 2180
    virCheckFlags(VIR_DUMP_CRASH, -1);

2181

2182
    if (!(privdom = testDomObjFromDomain(domain)))
2183
        goto cleanup;
2184 2185

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

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

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

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

2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241

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)
{
2242 2243 2244
    char *ret;

    ignore_value(VIR_STRDUP(ret, "linux"));
2245
    return ret;
2246 2247
}

2248 2249 2250

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

2255 2256
    if (!(privdom = testDomObjFromDomain(domain)))
        return 0;
2257

2258
    ret = virDomainDefGetMemoryTotal(privdom->def);
2259

2260
    virDomainObjEndAPI(&privdom);
2261
    return ret;
2262 2263
}

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

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

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

2275
    virDomainObjEndAPI(&privdom);
2276
    return 0;
2277 2278
}

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

2285 2286
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2287

2288
    if (memory > virDomainDefGetMemoryTotal(privdom->def)) {
2289
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2290
        goto cleanup;
2291
    }
2292

2293
    privdom->def->mem.cur_balloon = memory;
2294 2295
    ret = 0;

2296
 cleanup:
2297
    virDomainObjEndAPI(&privdom);
2298
    return ret;
2299 2300
}

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

2308 2309
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2310 2311
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

2312 2313
    if (!(vm = testDomObjFromDomain(domain)))
        return -1;
2314

2315
    if (!(def = virDomainObjGetOneDef(vm, flags)))
2316
        goto cleanup;
2317

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

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

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

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

2344 2345
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2346 2347
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

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

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

2358 2359
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2360

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

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

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

2380 2381 2382
    if (def &&
        virDomainDefSetVcpus(def, nrCpus) < 0)
        goto cleanup;
2383

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

2394 2395
    ret = 0;

2396
 cleanup:
2397
    virDomainObjEndAPI(&privdom);
2398
    return ret;
2399 2400
}

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

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

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

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

2432
    def = privdom->def;
C
Cole Robinson 已提交
2433 2434

    if (gettimeofday(&tv, NULL) < 0) {
2435
        virReportSystemError(errno,
C
Cole Robinson 已提交
2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446
                             "%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;

2447 2448 2449 2450 2451
    if (!(allcpumap = virBitmapNew(hostcpus)))
        goto cleanup;

    virBitmapSetAll(allcpumap);

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

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

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

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

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

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

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

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

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

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

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

2504 2505
    def = privdom->def;

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

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

2520 2521 2522
    virBitmapFree(vcpuinfo->cpumask);

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

    ret = 0;
2526

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

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

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

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

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

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

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

2566 2567
    /* Flags checked by virDomainDefFormat */

2568 2569
    if (!(privdom = testDomObjFromDomain(domain)))
        return NULL;
2570

2571 2572
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
2573

2574 2575
    ret = virDomainDefFormat(def, privconn->caps,
                             virDomainDefFormatConvertXMLFlags(flags));
2576

2577
    virDomainObjEndAPI(&privdom);
2578
    return ret;
2579
}
2580

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

2585
    return virDomainObjListNumOfDomains(privconn->domains, false, NULL, NULL);
2586 2587
}

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

2593
    testDriverPtr privconn = conn->privateData;
2594 2595

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

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

    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
2613

2614
    if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
2615
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
2616

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

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

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

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

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

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

2657 2658 2659 2660 2661 2662
static char *testDomainGetMetadata(virDomainPtr dom,
                                   int type,
                                   const char *uri,
                                   unsigned int flags)
{
    virDomainObjPtr privdom;
2663
    char *ret;
2664 2665 2666 2667

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, NULL);

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

2671
    ret = virDomainObjGetMetadata(privdom, type, uri, flags);
2672

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

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

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

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

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

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


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

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

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

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


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

2739 2740
    virCheckFlags(0, -1);

2741
    testDriverLock(privconn);
2742

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

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

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

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

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

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

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

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

2786

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

C
Cole Robinson 已提交
2790 2791 2792 2793 2794 2795 2796 2797
    if (privdom->hasManagedSave &&
        !(flags & VIR_DOMAIN_UNDEFINE_MANAGED_SAVE)) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("Refusing to undefine while domain managed "
                         "save image exists"));
        goto cleanup;
    }

2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815
    /* Requiring an inactive VM is part of the documented API for
     * UNDEFINE_SNAPSHOTS_METADATA
     */
    if (!virDomainObjIsActive(privdom) &&
        (nsnapshots = virDomainSnapshotObjListNum(privdom->snapshots,
                                                  NULL, 0))) {
        if (!(flags & VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA)) {
            virReportError(VIR_ERR_OPERATION_INVALID,
                           _("cannot delete inactive domain with %d "
                             "snapshots"),
                           nsnapshots);
            goto cleanup;
        }

        /* There isn't actually anything to do, we are just emulating qemu
         * behavior here. */
    }

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

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

2826
    ret = 0;
2827

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

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

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

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

2847
    *autostart = privdom->autostart;
2848

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


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

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

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

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

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

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

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

2878 2879 2880
    return type;
}

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

2890 2891
    virCheckFlags(0, -1);

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

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

    *nparams = 1;
2902 2903
    ret = 0;

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

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

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

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

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

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

2944 2945
    ret = 0;

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

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

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

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

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

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

    if (gettimeofday(&tv, NULL) < 0) {
2983
        virReportSystemError(errno,
2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996
                             "%s", _("getting time of day"));
        goto error;
    }

    /* No significance to these numbers, just enough to mix it up*/
    statbase = (tv.tv_sec * 1000UL * 1000UL) + tv.tv_usec;
    stats->rd_req = statbase / 10;
    stats->rd_bytes = statbase / 20;
    stats->wr_req = statbase / 30;
    stats->wr_bytes = statbase / 40;
    stats->errs = tv.tv_sec / 2;

    ret = 0;
2997
 error:
2998
    virDomainObjEndAPI(&privdom);
2999 3000 3001 3002 3003
    return ret;
}

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

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

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

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

    if (gettimeofday(&tv, NULL) < 0) {
3030
        virReportSystemError(errno,
3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046
                             "%s", _("getting time of day"));
        goto error;
    }

    /* No significance to these numbers, just enough to mix it up*/
    statbase = (tv.tv_sec * 1000UL * 1000UL) + tv.tv_usec;
    stats->rx_bytes = statbase / 10;
    stats->rx_packets = statbase / 100;
    stats->rx_errs = tv.tv_sec / 1;
    stats->rx_drop = tv.tv_sec / 2;
    stats->tx_bytes = statbase / 20;
    stats->tx_packets = statbase / 110;
    stats->tx_errs = tv.tv_sec / 3;
    stats->tx_drop = tv.tv_sec / 4;

    ret = 0;
3047
 error:
3048
    virDomainObjEndAPI(&privdom);
3049 3050 3051
    return ret;
}

3052

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
                  VIR_NETWORK_UPDATE_AFFECT_CONFIG,
                  -1);

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

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

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

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

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

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

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

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

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

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

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

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

3371 3372
    ret = 0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

C
Cole Robinson 已提交
3468

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


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

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

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

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

    return n;

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

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

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

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

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

    return n;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    privconn->transaction_running = true;

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

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

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

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

3676 3677 3678
    testDriverLock(privconn);

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

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

    ret = 0;

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

    return ret;
}

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

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

3704 3705 3706
    testDriverLock(privconn);

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

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

    privconn->transaction_running = false;

    ret = 0;

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    privinterface->active = 1;
    ret = 0;

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

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

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

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

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

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

    privinterface->active = 0;
    ret = 0;

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



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

3880

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

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

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

3891

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

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

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

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

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

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

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

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

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

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

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

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

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

    return numActive;
}

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

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

    return n;

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

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

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

    return numInactive;
}

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

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

    return n;

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

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

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

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

    return ret;
}
C
Cole Robinson 已提交
4064

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

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

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

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

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

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



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

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

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

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

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

    privpool->active = 1;
4137 4138 4139 4140

    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_STARTED,
                                            0);
4141
    ret = 0;
C
Cole Robinson 已提交
4142

4143
 cleanup:
4144
    testObjectEventQueue(privconn, event);
4145 4146
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4147
    return ret;
C
Cole Robinson 已提交
4148 4149 4150
}

static char *
4151 4152 4153 4154
testConnectFindStoragePoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type,
                                  const char *srcSpec,
                                  unsigned int flags)
C
Cole Robinson 已提交
4155
{
4156 4157 4158 4159
    virStoragePoolSourcePtr source = NULL;
    int pool_type;
    char *ret = NULL;

E
Eric Blake 已提交
4160 4161
    virCheckFlags(0, NULL);

4162 4163
    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
4164 4165
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
4166 4167 4168 4169
        goto cleanup;
    }

    if (srcSpec) {
4170
        source = virStoragePoolDefParseSourceString(srcSpec, pool_type);
4171 4172 4173 4174 4175 4176 4177
        if (!source)
            goto cleanup;
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
4178
        ignore_value(VIR_STRDUP(ret, defaultPoolSourcesLogicalXML));
4179 4180 4181
        break;

    case VIR_STORAGE_POOL_NETFS:
4182
        if (!source || !source->hosts[0].name) {
4183 4184
            virReportError(VIR_ERR_INVALID_ARG,
                           "%s", _("hostname must be specified for netfs sources"));
4185 4186 4187
            goto cleanup;
        }

4188 4189
        ignore_value(virAsprintf(&ret, defaultPoolSourcesNetFSXML,
                                 source->hosts[0].name));
4190 4191 4192
        break;

    default:
4193 4194
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source discovery"), type);
4195 4196
    }

4197
 cleanup:
4198 4199
    virStoragePoolSourceFree(source);
    return ret;
C
Cole Robinson 已提交
4200 4201 4202 4203
}


static virStoragePoolPtr
4204 4205 4206
testStoragePoolCreateXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4207
{
4208
    testDriverPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4209
    virStoragePoolDefPtr def;
4210
    virStoragePoolObjPtr pool = NULL;
4211
    virStoragePoolPtr ret = NULL;
4212
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
4213

E
Eric Blake 已提交
4214 4215
    virCheckFlags(0, NULL);

4216
    testDriverLock(privconn);
4217
    if (!(def = virStoragePoolDefParseString(xml)))
4218
        goto cleanup;
C
Cole Robinson 已提交
4219

4220 4221 4222 4223
    pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid);
    if (!pool)
        pool = virStoragePoolObjFindByName(&privconn->pools, def->name);
    if (pool) {
4224 4225
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("storage pool already exists"));
4226
        goto cleanup;
C
Cole Robinson 已提交
4227 4228
    }

4229
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4230
        goto cleanup;
4231
    def = NULL;
C
Cole Robinson 已提交
4232

4233
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4234
        virStoragePoolObjRemove(&privconn->pools, pool);
4235 4236
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4237 4238 4239
    }
    pool->active = 1;

4240 4241 4242 4243
    event = virStoragePoolEventLifecycleNew(pool->def->name, pool->def->uuid,
                                            VIR_STORAGE_POOL_EVENT_STARTED,
                                            0);

4244 4245
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4246

4247
 cleanup:
4248
    virStoragePoolDefFree(def);
4249
    testObjectEventQueue(privconn, event);
4250 4251 4252
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4253
    return ret;
C
Cole Robinson 已提交
4254 4255 4256
}

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

E
Eric Blake 已提交
4267 4268
    virCheckFlags(0, NULL);

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

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

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

4281 4282 4283 4284
    event = virStoragePoolEventLifecycleNew(pool->def->name, pool->def->uuid,
                                            VIR_STORAGE_POOL_EVENT_DEFINED,
                                            0);

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

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

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

static int
4304 4305
testStoragePoolUndefine(virStoragePoolPtr pool)
{
4306
    testDriverPtr privconn = pool->conn->privateData;
4307
    virStoragePoolObjPtr privpool;
4308
    int ret = -1;
4309
    virObjectEventPtr event = NULL;
4310

4311
    testDriverLock(privconn);
4312 4313 4314 4315
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
4316
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4317
        goto cleanup;
4318 4319
    }

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

4326 4327 4328 4329
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_UNDEFINED,
                                            0);

C
Cole Robinson 已提交
4330
    virStoragePoolObjRemove(&privconn->pools, privpool);
4331
    privpool = NULL;
4332
    ret = 0;
C
Cole Robinson 已提交
4333

4334
 cleanup:
4335 4336
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4337
    testObjectEventQueue(privconn, event);
4338
    testDriverUnlock(privconn);
4339
    return ret;
C
Cole Robinson 已提交
4340 4341 4342
}

static int
4343
testStoragePoolBuild(virStoragePoolPtr pool,
E
Eric Blake 已提交
4344 4345
                     unsigned int flags)
{
4346
    testDriverPtr privconn = pool->conn->privateData;
4347
    virStoragePoolObjPtr privpool;
4348
    int ret = -1;
4349

E
Eric Blake 已提交
4350 4351
    virCheckFlags(0, -1);

4352
    testDriverLock(privconn);
4353 4354
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4355
    testDriverUnlock(privconn);
4356 4357

    if (privpool == NULL) {
4358
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4359
        goto cleanup;
4360 4361
    }

4362
    if (virStoragePoolObjIsActive(privpool)) {
4363 4364
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4365 4366
        goto cleanup;
    }
4367
    ret = 0;
C
Cole Robinson 已提交
4368

4369
 cleanup:
4370 4371
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4372
    return ret;
C
Cole Robinson 已提交
4373 4374 4375 4376
}


static int
4377 4378
testStoragePoolDestroy(virStoragePoolPtr pool)
{
4379
    testDriverPtr privconn = pool->conn->privateData;
4380
    virStoragePoolObjPtr privpool;
4381
    int ret = -1;
4382
    virObjectEventPtr event = NULL;
4383

4384
    testDriverLock(privconn);
4385 4386 4387 4388
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
4389
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4390
        goto cleanup;
4391 4392 4393
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4394 4395
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4396
        goto cleanup;
4397
    }
C
Cole Robinson 已提交
4398 4399

    privpool->active = 0;
4400 4401 4402
    event = virStoragePoolEventLifecycleNew(privpool->def->name, privpool->def->uuid,
                                            VIR_STORAGE_POOL_EVENT_STOPPED,
                                            0);
C
Cole Robinson 已提交
4403

4404
    if (privpool->configFile == NULL) {
C
Cole Robinson 已提交
4405
        virStoragePoolObjRemove(&privconn->pools, privpool);
4406 4407
        privpool = NULL;
    }
4408
    ret = 0;
C
Cole Robinson 已提交
4409

4410
 cleanup:
4411
    testObjectEventQueue(privconn, event);
4412 4413 4414
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
4415
    return ret;
C
Cole Robinson 已提交
4416 4417 4418 4419
}


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

E
Eric Blake 已提交
4427 4428
    virCheckFlags(0, -1);

4429
    testDriverLock(privconn);
4430 4431
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4432
    testDriverUnlock(privconn);
4433 4434

    if (privpool == NULL) {
4435
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4436 4437 4438 4439
        goto cleanup;
    }

    if (virStoragePoolObjIsActive(privpool)) {
4440 4441
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4442
        goto cleanup;
4443 4444
    }

4445
    ret = 0;
C
Cole Robinson 已提交
4446

4447
 cleanup:
4448 4449
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4450
    return ret;
C
Cole Robinson 已提交
4451 4452 4453 4454
}


static int
4455
testStoragePoolRefresh(virStoragePoolPtr pool,
E
Eric Blake 已提交
4456 4457
                       unsigned int flags)
{
4458
    testDriverPtr privconn = pool->conn->privateData;
4459
    virStoragePoolObjPtr privpool;
4460
    int ret = -1;
4461
    virObjectEventPtr event = NULL;
4462

E
Eric Blake 已提交
4463 4464
    virCheckFlags(0, -1);

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

    if (privpool == NULL) {
4471
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4472
        goto cleanup;
4473 4474 4475
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4476 4477
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4478
        goto cleanup;
4479
    }
4480

4481
    event = virStoragePoolEventRefreshNew(pool->name, pool->uuid);
4482
    ret = 0;
C
Cole Robinson 已提交
4483

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

4643 4644
    ret = privpool->volumes.count;

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

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

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

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

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


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

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

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

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

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

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

    virCheckFlags(0, -1);

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

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

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

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

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

4738
    for (i = 0; i < pool->volumes.count; i++) {
4739 4740
        if (!(vol = virGetStorageVol(obj->conn, pool->def->name,
                                     pool->volumes.objs[i]->name,
4741 4742
                                     pool->volumes.objs[i]->key,
                                     NULL, NULL)))
4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756
            goto cleanup;
        tmp_vols[nvols++] = vol;
    }

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

 cleanup:
    if (tmp_vols) {
        for (i = 0; i < nvols; i++) {
            if (tmp_vols[i])
                virStorageVolFree(tmp_vols[i]);
        }
4757
        VIR_FREE(tmp_vols);
4758 4759 4760 4761 4762 4763 4764
    }

    if (pool)
        virStoragePoolObjUnlock(pool);

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

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

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

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


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

    privvol = virStorageVolDefFindByName(privpool, name);

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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


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

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

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

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


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

5103
    switch (pooltype) {
C
Cole Robinson 已提交
5104 5105 5106 5107 5108 5109 5110 5111 5112 5113
        case VIR_STORAGE_POOL_DIR:
        case VIR_STORAGE_POOL_FS:
        case VIR_STORAGE_POOL_NETFS:
            return VIR_STORAGE_VOL_FILE;
        default:
            return VIR_STORAGE_VOL_BLOCK;
    }
}

static int
5114
testStorageVolGetInfo(virStorageVolPtr vol,
5115 5116
                      virStorageVolInfoPtr info)
{
5117
    testDriverPtr privconn = vol->conn->privateData;
5118 5119
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5120
    int ret = -1;
5121

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

5244

5245
/* Node device implementations */
5246

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

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

5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272
    testDriverLock(driver);
    for (i = 0; i < driver->devs.count; i++)
        if ((cap == NULL) ||
            virNodeDeviceHasCap(driver->devs.objs[i], cap))
            ++ndevs;
    testDriverUnlock(driver);

    return ndevs;
}

static int
testNodeListDevices(virConnectPtr conn,
                    const char *cap,
                    char **const names,
                    int maxnames,
E
Eric Blake 已提交
5273
                    unsigned int flags)
5274
{
5275
    testDriverPtr driver = conn->privateData;
5276
    int ndevs = 0;
5277
    size_t i;
5278

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

5281 5282 5283 5284 5285
    testDriverLock(driver);
    for (i = 0; i < driver->devs.count && ndevs < maxnames; i++) {
        virNodeDeviceObjLock(driver->devs.objs[i]);
        if (cap == NULL ||
            virNodeDeviceHasCap(driver->devs.objs[i], cap)) {
5286
            if (VIR_STRDUP(names[ndevs++], driver->devs.objs[i]->def->name) < 0) {
5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307
                virNodeDeviceObjUnlock(driver->devs.objs[i]);
                goto failure;
            }
        }
        virNodeDeviceObjUnlock(driver->devs.objs[i]);
    }
    testDriverUnlock(driver);

    return ndevs;

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

static virNodeDevicePtr
testNodeDeviceLookupByName(virConnectPtr conn, const char *name)
{
5308
    testDriverPtr driver = conn->privateData;
5309 5310 5311 5312 5313 5314 5315 5316
    virNodeDeviceObjPtr obj;
    virNodeDevicePtr ret = NULL;

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

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

    ret = virGetNodeDevice(conn, name);

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

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

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

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

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

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

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

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

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

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

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

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

5391

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

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

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

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

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


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

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

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

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

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

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

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

5475 5476
    testDriverLock(driver);

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

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

5485
    if (virNodeDeviceGetParentHost(&driver->devs,
5486 5487 5488 5489 5490 5491 5492 5493 5494
                                   def->name,
                                   def->parent,
                                   &parent_host) == -1) {
        goto cleanup;
    }

    /* 'name' is supposed to be filled in by the node device backend, which
     * we don't have. Use WWPN instead. */
    VIR_FREE(def->name);
5495
    if (VIR_STRDUP(def->name, wwpn) < 0)
5496 5497
        goto cleanup;

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

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


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

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

static int
testNodeDeviceDestroy(virNodeDevicePtr dev)
{
    int ret = 0;
5529
    testDriverPtr driver = dev->conn->privateData;
5530 5531 5532 5533 5534 5535 5536 5537 5538
    virNodeDeviceObjPtr obj = NULL;
    char *parent_name = NULL, *wwnn = NULL, *wwpn = NULL;
    int parent_host = -1;

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

    if (!obj) {
5539 5540 5541
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5542 5543 5544
        goto out;
    }

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

5548
    if (VIR_STRDUP(parent_name, obj->def->parent) < 0)
5549 5550 5551 5552 5553 5554 5555 5556 5557
        goto out;

    /* virNodeDeviceGetParentHost will cause the device object's lock to be
     * taken, so we have to dup the parent's name and drop the lock
     * before calling it.  We don't need the reference to the object
     * any more once we have the parent's name.  */
    virNodeDeviceObjUnlock(obj);

    /* We do this just for basic validation */
5558
    if (virNodeDeviceGetParentHost(&driver->devs,
5559 5560 5561 5562 5563 5564 5565 5566 5567 5568
                                   dev->name,
                                   parent_name,
                                   &parent_host) == -1) {
        obj = NULL;
        goto out;
    }

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

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

5578 5579

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

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

    return ret;
}

5596

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

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

    return ret;
}

5611 5612

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

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

    return ret;
}

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

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

    return ret;
}


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

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

    return ret;
}

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

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

    return ret;
}

5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711
static int
testConnectStoragePoolEventRegisterAny(virConnectPtr conn,
                                       virStoragePoolPtr pool,
                                       int eventID,
                                       virConnectStoragePoolEventGenericCallback callback,
                                       void *opaque,
                                       virFreeCallback freecb)
{
    testDriverPtr driver = conn->privateData;
    int ret;

    if (virStoragePoolEventStateRegisterID(conn, driver->eventState,
                                           pool, eventID, callback,
                                           opaque, freecb, &ret) < 0)
        ret = -1;

    return ret;
}

static int
testConnectStoragePoolEventDeregisterAny(virConnectPtr conn,
                                         int callbackID)
{
    testDriverPtr driver = conn->privateData;
    int ret = 0;

    if (virObjectEventStateDeregisterID(conn, driver->eventState,
                                        callbackID) < 0)
        ret = -1;

    return ret;
}

5712 5713 5714
static int testConnectListAllDomains(virConnectPtr conn,
                                     virDomainPtr **domains,
                                     unsigned int flags)
5715
{
5716
    testDriverPtr privconn = conn->privateData;
5717

O
Osier Yang 已提交
5718
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
5719

5720 5721
    return virDomainObjListExport(privconn->domains, conn, domains,
                                  NULL, flags);
5722 5723
}

5724
static int
P
Peter Krempa 已提交
5725
testNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,
5726 5727 5728 5729 5730 5731 5732
                  unsigned char **cpumap,
                  unsigned int *online,
                  unsigned int flags)
{
    virCheckFlags(0, -1);

    if (cpumap) {
5733
        if (VIR_ALLOC_N(*cpumap, 1) < 0)
P
Peter Krempa 已提交
5734
            return -1;
5735 5736 5737 5738 5739 5740
        *cpumap[0] = 0x15;
    }

    if (online)
        *online = 3;

P
Peter Krempa 已提交
5741
    return  8;
5742 5743
}

5744 5745 5746 5747 5748 5749 5750 5751 5752 5753
static char *
testDomainScreenshot(virDomainPtr dom ATTRIBUTE_UNUSED,
                     virStreamPtr st,
                     unsigned int screen ATTRIBUTE_UNUSED,
                     unsigned int flags)
{
    char *ret = NULL;

    virCheckFlags(0, NULL);

5754
    if (VIR_STRDUP(ret, "image/png") < 0)
5755 5756
        return NULL;

5757
    if (virFDStreamOpenFile(st, PKGDATADIR "/libvirtLogo.png", 0, 0, O_RDONLY) < 0)
5758 5759 5760 5761 5762
        VIR_FREE(ret);

    return ret;
}

5763 5764 5765 5766 5767 5768 5769 5770 5771
static int
testConnectGetCPUModelNames(virConnectPtr conn ATTRIBUTE_UNUSED,
                            const char *arch,
                            char ***models,
                            unsigned int flags)
{
    virCheckFlags(0, -1);
    return cpuGetModels(arch, models);
}
5772

C
Cole Robinson 已提交
5773 5774 5775
static int
testDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
5776
    testDriverPtr privconn = dom->conn->privateData;
C
Cole Robinson 已提交
5777
    virDomainObjPtr vm = NULL;
5778
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
5779 5780 5781 5782 5783 5784
    int ret = -1;

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

5785 5786
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800

    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);
5801
    event = virDomainEventLifecycleNewFromObj(vm,
C
Cole Robinson 已提交
5802 5803 5804 5805 5806
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
    vm->hasManagedSave = true;

    ret = 0;
5807
 cleanup:
5808
    virDomainObjEndAPI(&vm);
5809
    testObjectEventQueue(privconn, event);
C
Cole Robinson 已提交
5810 5811 5812 5813 5814 5815 5816 5817 5818

    return ret;
}


static int
testDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm;
5819
    int ret;
C
Cole Robinson 已提交
5820 5821 5822

    virCheckFlags(0, -1);

5823 5824
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5825 5826

    ret = vm->hasManagedSave;
5827

5828
    virDomainObjEndAPI(&vm);
C
Cole Robinson 已提交
5829 5830 5831 5832 5833 5834 5835 5836 5837 5838
    return ret;
}

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

    virCheckFlags(0, -1);

5839 5840
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5841 5842

    vm->hasManagedSave = false;
5843

5844
    virDomainObjEndAPI(&vm);
5845
    return 0;
C
Cole Robinson 已提交
5846 5847 5848
}


5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882
/*
 * 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;
5883
    int n;
5884 5885 5886 5887 5888

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5889
        return -1;
5890 5891 5892

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

5893
    virDomainObjEndAPI(&vm);
5894 5895 5896 5897 5898 5899 5900 5901 5902 5903
    return n;
}

static int
testDomainSnapshotListNames(virDomainPtr domain,
                            char **names,
                            int nameslen,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
5904
    int n;
5905 5906 5907 5908 5909

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5910
        return -1;
5911 5912 5913 5914

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

5915
    virDomainObjEndAPI(&vm);
5916 5917 5918 5919 5920 5921 5922 5923 5924
    return n;
}

static int
testDomainListAllSnapshots(virDomainPtr domain,
                           virDomainSnapshotPtr **snaps,
                           unsigned int flags)
{
    virDomainObjPtr vm = NULL;
5925
    int n;
5926 5927 5928 5929 5930

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5931
        return -1;
5932 5933 5934

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

5935
    virDomainObjEndAPI(&vm);
5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952
    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)))
5953
        return -1;
5954 5955 5956 5957 5958 5959 5960

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

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

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

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

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

5985
 cleanup:
5986
    virDomainObjEndAPI(&vm);
5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002
    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)))
6003
        return -1;
6004 6005 6006 6007 6008 6009 6010

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

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

6011
 cleanup:
6012
    virDomainObjEndAPI(&vm);
6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027
    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)))
6028
        return NULL;
6029 6030 6031 6032 6033 6034

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

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

6035
 cleanup:
6036
    virDomainObjEndAPI(&vm);
6037 6038 6039 6040 6041 6042 6043 6044
    return snapshot;
}

static int
testDomainHasCurrentSnapshot(virDomainPtr domain,
                             unsigned int flags)
{
    virDomainObjPtr vm;
6045
    int ret;
6046 6047 6048 6049

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6050
        return -1;
6051 6052 6053

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

6054
    virDomainObjEndAPI(&vm);
6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068
    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)))
6069
        return NULL;
6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082

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

6083
 cleanup:
6084
    virDomainObjEndAPI(&vm);
6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097
    return parent;
}

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

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
6098
        return NULL;
6099 6100 6101 6102 6103 6104 6105 6106 6107

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

6108
 cleanup:
6109
    virDomainObjEndAPI(&vm);
6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120
    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];
6121
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6122 6123 6124 6125

    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6126
        return NULL;
6127 6128 6129 6130 6131 6132

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

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

6133
    xml = virDomainSnapshotDefFormat(uuidstr, snap->def, privconn->caps,
6134 6135
                                     virDomainDefFormatConvertXMLFlags(flags),
                                     0);
6136

6137
 cleanup:
6138
    virDomainObjEndAPI(&vm);
6139 6140 6141 6142 6143 6144 6145 6146
    return xml;
}

static int
testDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6147
    int ret;
6148 6149 6150 6151

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6152
        return -1;
6153 6154 6155 6156

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

6157
    virDomainObjEndAPI(&vm);
6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171
    return ret;
}


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

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6172
        return -1;
6173

C
Cole Robinson 已提交
6174
    if (!testSnapObjFromSnapshot(vm, snapshot))
6175 6176 6177 6178
        goto cleanup;

    ret = 1;

6179
 cleanup:
6180
    virDomainObjEndAPI(&vm);
6181 6182 6183
    return ret;
}

6184 6185 6186 6187 6188 6189
static int
testDomainSnapshotAlignDisks(virDomainObjPtr vm,
                             virDomainSnapshotDefPtr def,
                             unsigned int flags)
{
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
E
Eric Blake 已提交
6190
    bool align_match = true;
6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218

    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)
{
6219
    testDriverPtr privconn = domain->conn->privateData;
6220 6221 6222 6223
    virDomainObjPtr vm = NULL;
    virDomainSnapshotDefPtr def = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr snapshot = NULL;
6224
    virObjectEventPtr event = NULL;
6225
    char *xml = NULL;
6226 6227
    bool update_current = true;
    bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
6228 6229 6230 6231 6232 6233 6234 6235
    unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;

    /*
     * DISK_ONLY: Not implemented yet
     * REUSE_EXT: Not implemented yet
     *
     * NO_METADATA: Explicitly not implemented
     *
6236
     * REDEFINE + CURRENT: Implemented
6237 6238 6239 6240 6241 6242
     * HALT: Implemented
     * QUIESCE: Nothing to do
     * ATOMIC: Nothing to do
     * LIVE: Nothing to do
     */
    virCheckFlags(
6243 6244
        VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
        VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
6245 6246 6247 6248 6249
        VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
        VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
        VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
        VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, NULL);

6250 6251 6252 6253 6254
    if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)))
        update_current = false;
    if (redefine)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;

6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269
    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;

6270
    if (redefine) {
C
Cole Robinson 已提交
6271 6272
        if (virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
                                          &update_current, flags) < 0)
6273 6274 6275 6276 6277 6278 6279
            goto cleanup;
    } else {
        if (!(def->dom = virDomainDefCopy(vm->def,
                                          privconn->caps,
                                          privconn->xmlopt,
                                          true)))
            goto cleanup;
6280

6281
        if (testDomainSnapshotAlignDisks(vm, def, flags) < 0)
6282 6283 6284
            goto cleanup;
    }

6285 6286 6287 6288
    if (!snap) {
        if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
            goto cleanup;
        def = NULL;
6289 6290
    }

6291 6292 6293 6294 6295 6296 6297 6298 6299 6300
    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);
6301
            event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
6302 6303 6304
                                    VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
        }
    }
6305 6306

    snapshot = virGetDomainSnapshot(domain, snap->def->name);
6307
 cleanup:
6308 6309 6310 6311
    VIR_FREE(xml);
    if (vm) {
        if (snapshot) {
            virDomainSnapshotObjPtr other;
6312 6313
            if (update_current)
                vm->current_snapshot = snap;
6314 6315 6316 6317 6318 6319 6320
            other = virDomainSnapshotFindByName(vm->snapshots,
                                                snap->def->parent);
            snap->parent = other;
            other->nchildren++;
            snap->sibling = other->first_child;
            other->first_child = snap;
        }
6321
        virDomainObjEndAPI(&vm);
6322
    }
6323
    testObjectEventQueue(privconn, event);
6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335
    virDomainSnapshotDefFree(def);
    return snapshot;
}


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

6336
static int
6337
testDomainSnapshotDiscardAll(void *payload,
6338 6339
                             const void *name ATTRIBUTE_UNUSED,
                             void *data)
6340 6341 6342 6343 6344 6345 6346
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapRemoveDataPtr curr = data;

    if (snap->def->current)
        curr->current = true;
    virDomainSnapshotObjListRemove(curr->vm->snapshots, snap);
6347
    return 0;
6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358
}

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

6359
static int
6360 6361 6362 6363 6364 6365 6366
testDomainSnapshotReparentChildren(void *payload,
                                   const void *name ATTRIBUTE_UNUSED,
                                   void *data)
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapReparentDataPtr rep = data;

6367
    if (rep->err < 0)
6368
        return 0;
6369 6370 6371 6372 6373 6374 6375

    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;
6376
        return 0;
6377 6378 6379 6380
    }

    if (!snap->sibling)
        rep->last = snap;
6381
    return 0;
6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410
}

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) {
6411
            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)
6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454
                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;
6455
 cleanup:
6456
    virDomainObjEndAPI(&vm);
6457 6458 6459 6460 6461 6462 6463
    return ret;
}

static int
testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                           unsigned int flags)
{
6464
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6465 6466
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
6467 6468
    virObjectEventPtr event = NULL;
    virObjectEventPtr event2 = NULL;
6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559
    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);
6560
                event = virDomainEventLifecycleNewFromObj(vm,
6561 6562
                            VIR_DOMAIN_EVENT_STOPPED,
                            VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
6563
                testObjectEventQueue(privconn, event);
6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574
                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. */
6575
                event = virDomainEventLifecycleNewFromObj(vm,
6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588
                                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;
6589
            event = virDomainEventLifecycleNewFromObj(vm,
6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602
                                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 */
6603
                event2 = virDomainEventLifecycleNewFromObj(vm,
6604 6605 6606 6607 6608
                                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 已提交
6609
            virObjectUnref(event);
6610 6611 6612 6613
            event = NULL;

            if (was_stopped) {
                /* Transition 2 */
6614
                event = virDomainEventLifecycleNewFromObj(vm,
6615 6616 6617 6618
                                VIR_DOMAIN_EVENT_STARTED,
                                VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            } else if (was_running) {
                /* Transition 8 */
6619
                event = virDomainEventLifecycleNewFromObj(vm,
6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631
                                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);
6632
            event = virDomainEventLifecycleNewFromObj(vm,
6633 6634 6635 6636 6637 6638 6639 6640 6641
                                    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;

6642
            testObjectEventQueue(privconn, event);
6643
            event = virDomainEventLifecycleNewFromObj(vm,
6644 6645 6646
                            VIR_DOMAIN_EVENT_STARTED,
                            VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            if (paused) {
6647
                event2 = virDomainEventLifecycleNewFromObj(vm,
6648 6649 6650 6651 6652 6653 6654 6655
                                VIR_DOMAIN_EVENT_SUSPENDED,
                                VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
            }
        }
    }

    vm->current_snapshot = snap;
    ret = 0;
6656
 cleanup:
6657
    if (event) {
6658
        testObjectEventQueue(privconn, event);
6659
        testObjectEventQueue(privconn, event2);
C
Cole Robinson 已提交
6660
    } else {
C
Cédric Bosdonnat 已提交
6661
        virObjectUnref(event2);
6662
    }
6663
    virDomainObjEndAPI(&vm);
6664 6665 6666 6667 6668

    return ret;
}


6669

6670
static virHypervisorDriver testHypervisorDriver = {
6671
    .name = "Test",
6672 6673 6674
    .connectOpen = testConnectOpen, /* 0.1.1 */
    .connectClose = testConnectClose, /* 0.1.1 */
    .connectGetVersion = testConnectGetVersion, /* 0.1.1 */
6675
    .connectGetHostname = testConnectGetHostname, /* 0.6.3 */
6676
    .connectGetMaxVcpus = testConnectGetMaxVcpus, /* 0.3.2 */
6677
    .nodeGetInfo = testNodeGetInfo, /* 0.1.1 */
6678 6679 6680 6681
    .connectGetCapabilities = testConnectGetCapabilities, /* 0.2.1 */
    .connectListDomains = testConnectListDomains, /* 0.1.1 */
    .connectNumOfDomains = testConnectNumOfDomains, /* 0.1.1 */
    .connectListAllDomains = testConnectListAllDomains, /* 0.9.13 */
6682
    .domainCreateXML = testDomainCreateXML, /* 0.1.4 */
6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696
    .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 */
6697 6698
    .domainGetState = testDomainGetState, /* 0.9.2 */
    .domainSave = testDomainSave, /* 0.3.2 */
6699
    .domainSaveFlags = testDomainSaveFlags, /* 0.9.4 */
6700
    .domainRestore = testDomainRestore, /* 0.3.2 */
6701
    .domainRestoreFlags = testDomainRestoreFlags, /* 0.9.4 */
6702
    .domainCoreDump = testDomainCoreDump, /* 0.3.2 */
6703
    .domainCoreDumpWithFormat = testDomainCoreDumpWithFormat, /* 1.2.3 */
6704
    .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */
6705 6706 6707 6708
    .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */
    .domainGetVcpusFlags = testDomainGetVcpusFlags, /* 0.8.5 */
    .domainPinVcpu = testDomainPinVcpu, /* 0.7.3 */
    .domainGetVcpus = testDomainGetVcpus, /* 0.7.3 */
6709
    .domainGetVcpuPinInfo = testDomainGetVcpuPinInfo, /* 1.2.18 */
6710 6711
    .domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
    .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
6712 6713
    .connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
    .connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
6714 6715 6716
    .domainCreate = testDomainCreate, /* 0.1.11 */
    .domainCreateWithFlags = testDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = testDomainDefineXML, /* 0.1.11 */
6717
    .domainDefineXMLFlags = testDomainDefineXMLFlags, /* 1.2.12 */
6718
    .domainUndefine = testDomainUndefine, /* 0.1.11 */
6719
    .domainUndefineFlags = testDomainUndefineFlags, /* 0.9.4 */
6720 6721 6722
    .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
    .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
    .domainGetSchedulerType = testDomainGetSchedulerType, /* 0.3.2 */
6723 6724 6725 6726
    .domainGetSchedulerParameters = testDomainGetSchedulerParameters, /* 0.3.2 */
    .domainGetSchedulerParametersFlags = testDomainGetSchedulerParametersFlags, /* 0.9.2 */
    .domainSetSchedulerParameters = testDomainSetSchedulerParameters, /* 0.3.2 */
    .domainSetSchedulerParametersFlags = testDomainSetSchedulerParametersFlags, /* 0.9.2 */
6727 6728 6729
    .domainBlockStats = testDomainBlockStats, /* 0.7.0 */
    .domainInterfaceStats = testDomainInterfaceStats, /* 0.7.0 */
    .nodeGetCellsFreeMemory = testNodeGetCellsFreeMemory, /* 0.4.2 */
6730 6731 6732 6733
    .connectDomainEventRegister = testConnectDomainEventRegister, /* 0.6.0 */
    .connectDomainEventDeregister = testConnectDomainEventDeregister, /* 0.6.0 */
    .connectIsEncrypted = testConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = testConnectIsSecure, /* 0.7.3 */
6734 6735 6736
    .domainIsActive = testDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = testDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = testDomainIsUpdated, /* 0.8.6 */
6737 6738 6739
    .connectDomainEventRegisterAny = testConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = testConnectDomainEventDeregisterAny, /* 0.8.0 */
    .connectIsAlive = testConnectIsAlive, /* 0.9.8 */
6740
    .nodeGetCPUMap = testNodeGetCPUMap, /* 1.0.0 */
6741
    .domainScreenshot = testDomainScreenshot, /* 1.0.5 */
6742 6743
    .domainGetMetadata = testDomainGetMetadata, /* 1.1.3 */
    .domainSetMetadata = testDomainSetMetadata, /* 1.1.3 */
6744
    .connectGetCPUModelNames = testConnectGetCPUModelNames, /* 1.1.3 */
6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761
    .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 */
6762 6763 6764
    .domainSnapshotCreateXML = testDomainSnapshotCreateXML, /* 1.1.4 */
    .domainRevertToSnapshot = testDomainRevertToSnapshot, /* 1.1.4 */
    .domainSnapshotDelete = testDomainSnapshotDelete, /* 1.1.4 */
6765

E
Eric Blake 已提交
6766
    .connectBaselineCPU = testConnectBaselineCPU, /* 1.2.0 */
6767 6768 6769
};

static virNetworkDriver testNetworkDriver = {
6770 6771 6772 6773 6774
    .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 */
6775 6776
    .connectNetworkEventRegisterAny = testConnectNetworkEventRegisterAny, /* 1.2.1 */
    .connectNetworkEventDeregisterAny = testConnectNetworkEventDeregisterAny, /* 1.2.1 */
6777 6778 6779 6780
    .networkLookupByUUID = testNetworkLookupByUUID, /* 0.3.2 */
    .networkLookupByName = testNetworkLookupByName, /* 0.3.2 */
    .networkCreateXML = testNetworkCreateXML, /* 0.3.2 */
    .networkDefineXML = testNetworkDefineXML, /* 0.3.2 */
6781
    .networkUndefine = testNetworkUndefine, /* 0.3.2 */
6782
    .networkUpdate = testNetworkUpdate, /* 0.10.2 */
6783
    .networkCreate = testNetworkCreate, /* 0.3.2 */
6784 6785 6786 6787 6788 6789 6790
    .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 */
6791 6792
};

L
Laine Stump 已提交
6793
static virInterfaceDriver testInterfaceDriver = {
6794 6795 6796 6797 6798 6799
    .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 */
6800 6801 6802 6803 6804 6805
    .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 */
6806 6807 6808
    .interfaceChangeBegin = testInterfaceChangeBegin,   /* 0.9.2 */
    .interfaceChangeCommit = testInterfaceChangeCommit,  /* 0.9.2 */
    .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */
L
Laine Stump 已提交
6809 6810 6811
};


6812
static virStorageDriver testStorageDriver = {
6813 6814 6815 6816 6817 6818
    .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 */
6819 6820
    .connectStoragePoolEventRegisterAny = testConnectStoragePoolEventRegisterAny, /* 2.0.0 */
    .connectStoragePoolEventDeregisterAny = testConnectStoragePoolEventDeregisterAny, /* 2.0.0 */
6821 6822 6823
    .storagePoolLookupByName = testStoragePoolLookupByName, /* 0.5.0 */
    .storagePoolLookupByUUID = testStoragePoolLookupByUUID, /* 0.5.0 */
    .storagePoolLookupByVolume = testStoragePoolLookupByVolume, /* 0.5.0 */
6824 6825
    .storagePoolCreateXML = testStoragePoolCreateXML, /* 0.5.0 */
    .storagePoolDefineXML = testStoragePoolDefineXML, /* 0.5.0 */
6826 6827
    .storagePoolBuild = testStoragePoolBuild, /* 0.5.0 */
    .storagePoolUndefine = testStoragePoolUndefine, /* 0.5.0 */
6828
    .storagePoolCreate = testStoragePoolCreate, /* 0.5.0 */
6829 6830 6831 6832 6833 6834 6835
    .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 */
6836
    .storagePoolNumOfVolumes = testStoragePoolNumOfVolumes, /* 0.5.0 */
6837 6838 6839
    .storagePoolListVolumes = testStoragePoolListVolumes, /* 0.5.0 */
    .storagePoolListAllVolumes = testStoragePoolListAllVolumes, /* 0.10.2 */

6840 6841 6842 6843 6844 6845 6846 6847 6848
    .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 */
6849 6850
    .storagePoolIsActive = testStoragePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = testStoragePoolIsPersistent, /* 0.7.3 */
6851 6852
};

6853
static virNodeDeviceDriver testNodeDeviceDriver = {
6854 6855 6856 6857 6858 6859 6860 6861 6862
    .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 */
6863 6864
};

6865 6866 6867 6868 6869 6870 6871 6872
static virConnectDriver testConnectDriver = {
    .hypervisorDriver = &testHypervisorDriver,
    .interfaceDriver = &testInterfaceDriver,
    .networkDriver = &testNetworkDriver,
    .nodeDeviceDriver = &testNodeDeviceDriver,
    .nwfilterDriver = NULL,
    .secretDriver = NULL,
    .storageDriver = &testStorageDriver,
6873 6874
};

6875 6876 6877 6878 6879 6880 6881 6882
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
6883 6884
    return virRegisterConnectDriver(&testConnectDriver,
                                    false);
6885
}