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

67 68
#define VIR_FROM_THIS VIR_FROM_TEST

69 70
VIR_LOG_INIT("test.test_driver");

71

72 73 74 75 76
#define MAX_CPUS 128

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

#define MAX_CELLS 128
83

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

91
struct _testDriver {
92
    virMutex lock;
93

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

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

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

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

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

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

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

161

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

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

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

    virObjectEventStateQueue(driver->eventState, event);
}

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

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

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

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

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

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

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

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

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

293 294 295
    *data = nsdata;
    return 0;

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

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

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

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

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

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

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


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

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

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

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

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

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

369
    return caps;
370

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

376

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

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

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

    return ret;

 error:
    testDriverFree(ret);
    return NULL;
}


411 412
static const char *defaultConnXML =
"<node>"
413 414
"<domain type='test'>"
"  <name>test</name>"
415
"  <uuid>6695eb01-f6a4-8304-79aa-97f2502e193f</uuid>"
416 417 418 419 420 421
"  <memory>8388608</memory>"
"  <currentMemory>2097152</currentMemory>"
"  <vcpu>2</vcpu>"
"  <os>"
"    <type>hvm</type>"
"  </os>"
422 423
"</domain>"
""
424 425
"<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
"    </dhcp>"
"  </ip>"
434 435
"</network>"
""
L
Laine Stump 已提交
436 437 438 439 440 441 442 443
"<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>"
444 445
"</interface>"
""
C
Cole Robinson 已提交
446 447
"<pool type='dir'>"
"  <name>default-pool</name>"
448
"  <uuid>dfe224cb-28fb-8dd0-c4b2-64eb3f0f4566</uuid>"
C
Cole Robinson 已提交
449 450 451
"  <target>"
"    <path>/default-pool</path>"
"  </target>"
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469
"</pool>"
""
"<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>"
470 471 472 473 474 475 476 477 478 479 480 481
"<device>"
"  <name>test-scsi-host-vport</name>"
"  <parent>computer</parent>"
"  <capability type='scsi_host'>"
"    <host>1</host>"
"    <capability type='fc_host'>"
"      <wwnn>2000000012341234</wwnn>"
"      <wwpn>1000000012341234</wwpn>"
"    </capability>"
"    <capability type='vport_ops'/>"
"  </capability>"
"</device>"
482 483
"</node>";

C
Cole Robinson 已提交
484

485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
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";

508
static const unsigned long long defaultPoolCap = (100 * 1024 * 1024 * 1024ull);
509
static const unsigned long long defaultPoolAlloc;
C
Cole Robinson 已提交
510

511
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool);
512
static int testNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
513

514 515 516 517
static virDomainObjPtr
testDomObjFromDomain(virDomainPtr domain)
{
    virDomainObjPtr vm;
518
    testDriverPtr driver = domain->conn->privateData;
519 520
    char uuidstr[VIR_UUID_STRING_BUFLEN];

521
    vm = virDomainObjListFindByUUIDRef(driver->domains, domain->uuid);
522 523 524 525 526 527 528 529 530 531
    if (!vm) {
        virUUIDFormat(domain->uuid, uuidstr);
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching uuid '%s' (%s)"),
                       uuidstr, domain->name);
    }

    return vm;
}

532
static char *
533 534
testDomainGenerateIfname(virDomainDefPtr domdef)
{
535
    int maxif = 1024;
536 537
    int ifctr;
    size_t i;
538 539 540 541 542

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

543
        if (virAsprintf(&ifname, "testnet%d", ifctr) < 0)
544 545 546
            return NULL;

        /* Generate network interface names */
547
        for (i = 0; i < domdef->nnets; i++) {
548
            if (domdef->nets[i]->ifname &&
549
                STREQ(domdef->nets[i]->ifname, ifname)) {
550 551 552 553 554 555 556
                found = 1;
                break;
            }
        }

        if (!found)
            return ifname;
557
        VIR_FREE(ifname);
558 559
    }

560 561
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Exceeded max iface limit %d"), maxif);
562 563 564
    return NULL;
}

565
static int
566
testDomainGenerateIfnames(virDomainDefPtr domdef)
567
{
568
    size_t i = 0;
569 570 571 572 573 574

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

575
        ifname = testDomainGenerateIfname(domdef);
576
        if (!ifname)
577
            return -1;
578 579 580 581

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

582
    return 0;
583 584
}

585

586 587
static void
testDomainShutdownState(virDomainPtr domain,
J
Jiri Denemark 已提交
588 589
                        virDomainObjPtr privdom,
                        virDomainShutoffReason reason)
590 591 592 593 594 595 596
{
    if (privdom->newDef) {
        virDomainDefFree(privdom->def);
        privdom->def = privdom->newDef;
        privdom->newDef = NULL;
    }

J
Jiri Denemark 已提交
597
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF, reason);
598 599 600 601 602
    privdom->def->id = -1;
    if (domain)
        domain->id = -1;
}

603
/* Set up domain runtime state */
604
static int
605
testDomainStartState(testDriverPtr privconn,
J
Jiri Denemark 已提交
606 607
                     virDomainObjPtr dom,
                     virDomainRunningReason reason)
608
{
609
    int ret = -1;
610

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

614
    if (virDomainObjSetDefTransient(privconn->caps,
615
                                    privconn->xmlopt,
616
                                    dom) < 0) {
617 618 619
        goto cleanup;
    }

C
Cole Robinson 已提交
620
    dom->hasManagedSave = false;
621
    ret = 0;
622
 cleanup:
623
    if (ret < 0)
J
Jiri Denemark 已提交
624
        testDomainShutdownState(NULL, dom, VIR_DOMAIN_SHUTOFF_FAILED);
625
    return ret;
626
}
627

628

629
static char *testBuildFilename(const char *relativeTo,
630 631
                               const char *filename)
{
632 633
    char *offset;
    int baseLen;
634 635
    char *ret;

636
    if (!filename || filename[0] == '\0')
637
        return NULL;
638 639 640 641
    if (filename[0] == '/') {
        ignore_value(VIR_STRDUP(ret, filename));
        return ret;
    }
642

643
    offset = strrchr(relativeTo, '/');
644
    if ((baseLen = (offset-relativeTo+1))) {
645
        char *absFile;
C
Chris Lalancette 已提交
646 647
        int totalLen = baseLen + strlen(filename) + 1;
        if (VIR_ALLOC_N(absFile, totalLen) < 0)
648
            return NULL;
C
Chris Lalancette 已提交
649 650 651 652
        if (virStrncpy(absFile, relativeTo, baseLen, totalLen) == NULL) {
            VIR_FREE(absFile);
            return NULL;
        }
653 654 655
        strcat(absFile, filename);
        return absFile;
    } else {
656 657
        ignore_value(VIR_STRDUP(ret, filename));
        return ret;
658
    }
659 660
}

C
Cole Robinson 已提交
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691
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;
    }

692
 error:
C
Cole Robinson 已提交
693 694 695 696 697
    xmlFreeDoc(doc);
    VIR_FREE(absFile);
    return ret;
}

698 699 700
static int
testParseNodeInfo(virNodeInfoPtr nodeInfo, xmlXPathContextPtr ctxt)
{
701
    char *str;
702 703
    long l;
    int ret;
704

705
    ret = virXPathLong("string(/node/cpu/nodes[1])", ctxt, &l);
706 707 708
    if (ret == 0) {
        nodeInfo->nodes = l;
    } else if (ret == -2) {
709 710
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu nodes value"));
711
        goto error;
712
    }
713

714
    ret = virXPathLong("string(/node/cpu/sockets[1])", ctxt, &l);
715 716 717
    if (ret == 0) {
        nodeInfo->sockets = l;
    } else if (ret == -2) {
718 719
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu sockets value"));
720
        goto error;
721
    }
722

723
    ret = virXPathLong("string(/node/cpu/cores[1])", ctxt, &l);
724 725 726
    if (ret == 0) {
        nodeInfo->cores = l;
    } else if (ret == -2) {
727 728
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu cores value"));
729
        goto error;
730 731
    }

732
    ret = virXPathLong("string(/node/cpu/threads[1])", ctxt, &l);
733 734 735
    if (ret == 0) {
        nodeInfo->threads = l;
    } else if (ret == -2) {
736 737
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu threads value"));
738
        goto error;
739
    }
740

741 742
    nodeInfo->cpus = (nodeInfo->cores * nodeInfo->threads *
                      nodeInfo->sockets * nodeInfo->nodes);
743
    ret = virXPathLong("string(/node/cpu/active[1])", ctxt, &l);
744
    if (ret == 0) {
745
        if (l < nodeInfo->cpus)
746
            nodeInfo->cpus = l;
747
    } else if (ret == -2) {
748 749
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu active value"));
750
        goto error;
751
    }
752
    ret = virXPathLong("string(/node/cpu/mhz[1])", ctxt, &l);
753 754 755
    if (ret == 0) {
        nodeInfo->mhz = l;
    } else if (ret == -2) {
756 757
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu mhz value"));
758
        goto error;
759 760
    }

761
    str = virXPathString("string(/node/cpu/model[1])", ctxt);
762
    if (str != NULL) {
C
Chris Lalancette 已提交
763
        if (virStrcpyStatic(nodeInfo->model, str) == NULL) {
764 765
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Model %s too big for destination"), str);
C
Chris Lalancette 已提交
766 767 768
            VIR_FREE(str);
            goto error;
        }
769
        VIR_FREE(str);
770 771
    }

772
    ret = virXPathLong("string(/node/memory[1])", ctxt, &l);
773 774 775
    if (ret == 0) {
        nodeInfo->memory = l;
    } else if (ret == -2) {
776 777
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node memory value"));
778
        goto error;
779
    }
780

781
    return 0;
782
 error:
783 784 785
    return -1;
}

786
static int
787
testParseDomainSnapshots(testDriverPtr privconn,
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 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837
                         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;
838
 error:
839 840 841
    return ret;
}

842
static int
843
testParseDomains(testDriverPtr privconn,
C
Cole Robinson 已提交
844 845
                 const char *file,
                 xmlXPathContextPtr ctxt)
846 847 848 849 850 851 852
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virDomainObjPtr obj;

    num = virXPathNodeSet("/node/domain", ctxt, &nodes);
853
    if (num < 0)
854 855
        goto error;

856
    for (i = 0; i < num; i++) {
857
        virDomainDefPtr def;
858
        testDomainNamespaceDefPtr nsdata;
C
Cole Robinson 已提交
859 860 861 862 863 864
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file, "domain");
        if (!node)
            goto error;

        def = virDomainDefParseNode(ctxt->doc, node,
                                    privconn->caps, privconn->xmlopt,
865
                                    VIR_DOMAIN_DEF_PARSE_INACTIVE);
C
Cole Robinson 已提交
866 867
        if (!def)
            goto error;
868

869
        if (testDomainGenerateIfnames(def) < 0 ||
870
            !(obj = virDomainObjListAdd(privconn->domains,
871
                                        def,
872
                                        privconn->xmlopt,
873
                                        0, NULL))) {
874
            virDomainDefFree(def);
875 876
            goto error;
        }
877

878 879 880 881 882
        if (testParseDomainSnapshots(privconn, obj, file, ctxt) < 0) {
            virObjectUnlock(obj);
            goto error;
        }

883
        nsdata = def->namespaceData;
884
        obj->persistent = !nsdata->transient;
C
Cole Robinson 已提交
885
        obj->hasManagedSave = nsdata->hasManagedSave;
886 887 888 889 890 891 892 893 894

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

898
        virObjectUnlock(obj);
899
    }
900

901
    ret = 0;
902
 error:
903 904 905 906 907
    VIR_FREE(nodes);
    return ret;
}

static int
908
testParseNetworks(testDriverPtr privconn,
C
Cole Robinson 已提交
909 910
                  const char *file,
                  xmlXPathContextPtr ctxt)
911 912 913 914 915 916 917
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virNetworkObjPtr obj;

    num = virXPathNodeSet("/node/network", ctxt, &nodes);
918
    if (num < 0)
919
        goto error;
920 921

    for (i = 0; i < num; i++) {
922
        virNetworkDefPtr def;
C
Cole Robinson 已提交
923 924 925
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file, "network");
        if (!node)
            goto error;
926

C
Cole Robinson 已提交
927 928 929
        def = virNetworkDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
930

931
        if (!(obj = virNetworkAssignDef(privconn->networks, def, 0))) {
932 933
            virNetworkDefFree(def);
            goto error;
934
        }
935 936

        obj->active = 1;
937
        virNetworkObjEndAPI(&obj);
938
    }
939

940
    ret = 0;
941
 error:
942 943 944 945 946
    VIR_FREE(nodes);
    return ret;
}

static int
947
testParseInterfaces(testDriverPtr privconn,
C
Cole Robinson 已提交
948 949
                    const char *file,
                    xmlXPathContextPtr ctxt)
950 951 952 953 954 955 956
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virInterfaceObjPtr obj;

    num = virXPathNodeSet("/node/interface", ctxt, &nodes);
957
    if (num < 0)
L
Laine Stump 已提交
958
        goto error;
959 960

    for (i = 0; i < num; i++) {
L
Laine Stump 已提交
961
        virInterfaceDefPtr def;
C
Cole Robinson 已提交
962 963 964 965
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "interface");
        if (!node)
            goto error;
L
Laine Stump 已提交
966

C
Cole Robinson 已提交
967 968 969
        def = virInterfaceDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
970

971
        if (!(obj = virInterfaceAssignDef(&privconn->ifaces, def))) {
L
Laine Stump 已提交
972 973 974
            virInterfaceDefFree(def);
            goto error;
        }
975

976 977 978 979 980
        obj->active = 1;
        virInterfaceObjUnlock(obj);
    }

    ret = 0;
981
 error:
982 983 984 985 986
    VIR_FREE(nodes);
    return ret;
}

static int
C
Cole Robinson 已提交
987
testOpenVolumesForPool(const char *file,
988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
                       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);
1004
    if (num < 0)
1005 1006 1007
        goto error;

    for (i = 0; i < num; i++) {
C
Cole Robinson 已提交
1008 1009 1010 1011
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "volume");
        if (!node)
            goto error;
1012

1013
        def = virStorageVolDefParseNode(pool->def, ctxt->doc, node, 0);
C
Cole Robinson 已提交
1014 1015
        if (!def)
            goto error;
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025

        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;
1026 1027
        if (VIR_APPEND_ELEMENT_COPY(pool->volumes.objs, pool->volumes.count, def) < 0)
            goto error;
1028

1029
        pool->def->allocation += def->target.allocation;
1030 1031 1032
        pool->def->available = (pool->def->capacity -
                                pool->def->allocation);
        def = NULL;
L
Laine Stump 已提交
1033 1034
    }

1035
    ret = 0;
1036
 error:
1037 1038 1039 1040 1041 1042
    virStorageVolDefFree(def);
    VIR_FREE(nodes);
    return ret;
}

static int
1043
testParseStorage(testDriverPtr privconn,
C
Cole Robinson 已提交
1044 1045
                 const char *file,
                 xmlXPathContextPtr ctxt)
1046 1047 1048 1049 1050 1051 1052
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virStoragePoolObjPtr obj;

    num = virXPathNodeSet("/node/pool", ctxt, &nodes);
1053
    if (num < 0)
C
Cole Robinson 已提交
1054
        goto error;
1055 1056

    for (i = 0; i < num; i++) {
C
Cole Robinson 已提交
1057
        virStoragePoolDefPtr def;
C
Cole Robinson 已提交
1058 1059 1060 1061
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "pool");
        if (!node)
            goto error;
C
Cole Robinson 已提交
1062

C
Cole Robinson 已提交
1063 1064 1065
        def = virStoragePoolDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
C
Cole Robinson 已提交
1066

1067
        if (!(obj = virStoragePoolObjAssignDef(&privconn->pools,
C
Cole Robinson 已提交
1068 1069 1070 1071 1072
                                                def))) {
            virStoragePoolDefFree(def);
            goto error;
        }

1073 1074
        if (testStoragePoolObjSetDefaults(obj) == -1) {
            virStoragePoolObjUnlock(obj);
C
Cole Robinson 已提交
1075
            goto error;
1076
        }
1077
        obj->active = 1;
1078 1079

        /* Find storage volumes */
C
Cole Robinson 已提交
1080
        if (testOpenVolumesForPool(file, ctxt, obj, i+1) < 0) {
1081
            virStoragePoolObjUnlock(obj);
1082 1083 1084
            goto error;
        }

1085
        virStoragePoolObjUnlock(obj);
C
Cole Robinson 已提交
1086 1087
    }

1088
    ret = 0;
1089
 error:
1090 1091 1092 1093 1094
    VIR_FREE(nodes);
    return ret;
}

static int
1095
testParseNodedevs(testDriverPtr privconn,
C
Cole Robinson 已提交
1096 1097
                  const char *file,
                  xmlXPathContextPtr ctxt)
1098 1099 1100 1101 1102 1103 1104
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virNodeDeviceObjPtr obj;

    num = virXPathNodeSet("/node/device", ctxt, &nodes);
1105
    if (num < 0)
1106
        goto error;
1107 1108

    for (i = 0; i < num; i++) {
1109
        virNodeDeviceDefPtr def;
C
Cole Robinson 已提交
1110 1111 1112 1113
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                  "nodedev");
        if (!node)
            goto error;
1114

C
Cole Robinson 已提交
1115 1116 1117
        def = virNodeDeviceDefParseNode(ctxt->doc, node, 0, NULL);
        if (!def)
            goto error;
1118 1119

        if (!(obj = virNodeDeviceAssignDef(&privconn->devs, def))) {
1120 1121 1122
            virNodeDeviceDefFree(def);
            goto error;
        }
1123 1124 1125 1126 1127

        virNodeDeviceObjUnlock(obj);
    }

    ret = 0;
1128
 error:
1129 1130 1131 1132
    VIR_FREE(nodes);
    return ret;
}

1133
static int
1134
testParseAuthUsers(testDriverPtr privconn,
1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167
                   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;
1168
 error:
1169 1170 1171
    VIR_FREE(nodes);
    return ret;
}
1172

C
Cole Robinson 已提交
1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203
static int
testOpenParse(testDriverPtr privconn,
              const char *file,
              xmlXPathContextPtr ctxt)
{
    if (!xmlStrEqual(ctxt->node->name, BAD_CAST "node")) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("Root element is not 'node'"));
        goto error;
    }

    if (testParseNodeInfo(&privconn->nodeInfo, ctxt) < 0)
        goto error;
    if (testParseDomains(privconn, file, ctxt) < 0)
        goto error;
    if (testParseNetworks(privconn, file, ctxt) < 0)
        goto error;
    if (testParseInterfaces(privconn, file, ctxt) < 0)
        goto error;
    if (testParseStorage(privconn, file, ctxt) < 0)
        goto error;
    if (testParseNodedevs(privconn, file, ctxt) < 0)
        goto error;
    if (testParseAuthUsers(privconn, ctxt) < 0)
        goto error;

    return 0;
 error:
    return -1;
}

1204 1205
/* No shared state between simultaneous test connections initialized
 * from a file.  */
1206 1207 1208 1209 1210
static int
testOpenFromFile(virConnectPtr conn, const char *file)
{
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
1211
    testDriverPtr privconn;
1212

1213
    if (!(privconn = testDriverNew()))
1214
        return VIR_DRV_OPEN_ERROR;
1215

1216 1217 1218 1219 1220 1221
    testDriverLock(privconn);
    conn->privateData = privconn;

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

1222
    if (!(doc = virXMLParseFileCtxt(file, &ctxt)))
1223 1224 1225 1226 1227
        goto error;

    privconn->numCells = 0;
    memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));

C
Cole Robinson 已提交
1228
    if (testOpenParse(privconn, file, ctxt) < 0)
1229
        goto error;
1230

J
Jim Meyering 已提交
1231
    xmlXPathFreeContext(ctxt);
1232
    xmlFreeDoc(doc);
1233
    testDriverUnlock(privconn);
1234

1235
    return 0;
1236 1237

 error:
J
Jim Meyering 已提交
1238
    xmlXPathFreeContext(ctxt);
1239
    xmlFreeDoc(doc);
1240
    testDriverFree(privconn);
1241
    conn->privateData = NULL;
1242
    return VIR_DRV_OPEN_ERROR;
1243 1244
}

1245 1246 1247 1248 1249 1250 1251 1252
/* 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)
{
    int u;
    testDriverPtr privconn = NULL;
1253 1254
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289

    virMutexLock(&defaultLock);
    if (defaultConnections++) {
        conn->privateData = defaultConn;
        virMutexUnlock(&defaultLock);
        return VIR_DRV_OPEN_SUCCESS;
    }

    if (!(privconn = testDriverNew()))
        goto error;

    conn->privateData = privconn;

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

    /* Numa setup */
    privconn->numCells = 2;
    for (u = 0; u < 2; ++u) {
        privconn->cells[u].numCpus = 8;
        privconn->cells[u].mem = (u + 1) * 2048 * 1024;
    }
    for (u = 0; u < 16; u++) {
        virBitmapPtr siblings = virBitmapNew(16);
        if (!siblings)
            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;
    }

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

1290 1291
    if (!(doc = virXMLParseStringCtxt(defaultConnXML,
                                      _("(test driver)"), &ctxt)))
1292 1293
        goto error;

1294
    if (testOpenParse(privconn, NULL, ctxt) < 0)
1295 1296 1297 1298
        goto error;

    defaultConn = privconn;

1299 1300
    xmlXPathFreeContext(ctxt);
    xmlFreeDoc(doc);
1301 1302 1303 1304 1305 1306
    virMutexUnlock(&defaultLock);

    return VIR_DRV_OPEN_SUCCESS;

 error:
    testDriverFree(privconn);
1307 1308
    xmlXPathFreeContext(ctxt);
    xmlFreeDoc(doc);
1309 1310 1311 1312 1313 1314
    conn->privateData = NULL;
    defaultConnections--;
    virMutexUnlock(&defaultLock);
    return VIR_DRV_OPEN_ERROR;
}

1315 1316 1317 1318
static int
testConnectAuthenticate(virConnectPtr conn,
                        virConnectAuthPtr auth)
{
1319
    testDriverPtr privconn = conn->privateData;
1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343
    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;

1344
 found_user:
1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363
    /* 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;
1364
 cleanup:
1365 1366 1367 1368
    VIR_FREE(username);
    VIR_FREE(password);
    return ret;
}
1369

1370
static virDrvOpenStatus testConnectOpen(virConnectPtr conn,
1371
                                        virConnectAuthPtr auth,
1372
                                        virConfPtr conf ATTRIBUTE_UNUSED,
1373
                                        unsigned int flags)
1374
{
1375
    int ret;
1376

E
Eric Blake 已提交
1377 1378
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

1379
    if (!conn->uri)
1380
        return VIR_DRV_OPEN_DECLINED;
1381

1382
    if (!conn->uri->scheme || STRNEQ(conn->uri->scheme, "test"))
1383
        return VIR_DRV_OPEN_DECLINED;
1384

1385
    /* Remote driver should handle these. */
1386
    if (conn->uri->server)
1387 1388
        return VIR_DRV_OPEN_DECLINED;

1389
    /* From this point on, the connection is for us. */
1390 1391 1392
    if (!conn->uri->path
        || conn->uri->path[0] == '\0'
        || (conn->uri->path[0] == '/' && conn->uri->path[1] == '\0')) {
1393 1394
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("testOpen: supply a path or use test:///default"));
1395 1396
        return VIR_DRV_OPEN_ERROR;
    }
1397

1398
    if (STREQ(conn->uri->path, "/default"))
1399 1400
        ret = testOpenDefault(conn);
    else
1401
        ret = testOpenFromFile(conn,
1402
                               conn->uri->path);
1403

1404 1405 1406
    if (ret != VIR_DRV_OPEN_SUCCESS)
        return ret;

1407 1408 1409 1410
    /* Fake authentication. */
    if (testConnectAuthenticate(conn, auth) < 0)
        return VIR_DRV_OPEN_ERROR;

1411
    return VIR_DRV_OPEN_SUCCESS;
1412 1413
}

1414
static int testConnectClose(virConnectPtr conn)
1415
{
1416
    testDriverPtr privconn = conn->privateData;
1417
    bool dflt = false;
1418

1419 1420
    if (privconn == defaultConn) {
        dflt = true;
1421 1422 1423 1424 1425 1426 1427
        virMutexLock(&defaultLock);
        if (--defaultConnections) {
            virMutexUnlock(&defaultLock);
            return 0;
        }
    }

1428
    testDriverLock(privconn);
1429
    testDriverFree(privconn);
1430 1431 1432

    if (dflt) {
        defaultConn = NULL;
1433
        virMutexUnlock(&defaultLock);
1434 1435
    }

1436
    conn->privateData = NULL;
1437
    return 0;
1438 1439
}

1440 1441
static int testConnectGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
                                 unsigned long *hvVer)
1442
{
1443
    *hvVer = 2;
1444
    return 0;
1445 1446
}

1447 1448 1449 1450 1451 1452
static char *testConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return virGetHostname();
}


1453
static int testConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
1454 1455 1456 1457
{
    return 1;
}

1458
static int testConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
1459 1460 1461 1462
{
    return 0;
}

1463
static int testConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
1464 1465 1466 1467
{
    return 1;
}

1468 1469
static int testConnectGetMaxVcpus(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type ATTRIBUTE_UNUSED)
1470 1471 1472 1473
{
    return 32;
}

1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488
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;
}

1489 1490
static int testNodeGetInfo(virConnectPtr conn,
                           virNodeInfoPtr info)
1491
{
1492
    testDriverPtr privconn = conn->privateData;
1493
    testDriverLock(privconn);
1494
    memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo));
1495
    testDriverUnlock(privconn);
1496
    return 0;
1497 1498
}

1499
static char *testConnectGetCapabilities(virConnectPtr conn)
1500
{
1501
    testDriverPtr privconn = conn->privateData;
1502
    char *xml;
1503
    testDriverLock(privconn);
1504
    xml = virCapabilitiesFormatXML(privconn->caps);
1505
    testDriverUnlock(privconn);
1506
    return xml;
1507 1508
}

1509
static int testConnectNumOfDomains(virConnectPtr conn)
1510
{
1511
    testDriverPtr privconn = conn->privateData;
1512
    int count;
1513

1514
    testDriverLock(privconn);
1515
    count = virDomainObjListNumOfDomains(privconn->domains, true, NULL, NULL);
1516
    testDriverUnlock(privconn);
1517

1518
    return count;
1519 1520
}

1521 1522 1523
static int testDomainIsActive(virDomainPtr dom)
{
    virDomainObjPtr obj;
1524
    int ret;
1525

1526 1527
    if (!(obj = testDomObjFromDomain(dom)))
        return -1;
1528

1529 1530
    ret = virDomainObjIsActive(obj);
    virDomainObjEndAPI(&obj);
1531 1532 1533 1534 1535 1536
    return ret;
}

static int testDomainIsPersistent(virDomainPtr dom)
{
    virDomainObjPtr obj;
1537 1538 1539 1540
    int ret;

    if (!(obj = testDomObjFromDomain(dom)))
        return -1;
1541 1542 1543

    ret = obj->persistent;

1544
    virDomainObjEndAPI(&obj);
1545 1546 1547
    return ret;
}

1548 1549 1550 1551 1552
static int testDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
{
    return 0;
}

1553
static virDomainPtr
1554
testDomainCreateXML(virConnectPtr conn, const char *xml,
1555
                      unsigned int flags)
1556
{
1557
    testDriverPtr privconn = conn->privateData;
1558
    virDomainPtr ret = NULL;
1559
    virDomainDefPtr def;
1560
    virDomainObjPtr dom = NULL;
1561
    virObjectEventPtr event = NULL;
1562
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
1563

1564 1565 1566
    virCheckFlags(VIR_DOMAIN_START_VALIDATE, NULL);

    if (flags & VIR_DOMAIN_START_VALIDATE)
1567
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
1568

1569
    testDriverLock(privconn);
1570
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
1571
                                       parse_flags)) == NULL)
1572
        goto cleanup;
1573

1574
    if (testDomainGenerateIfnames(def) < 0)
1575
        goto cleanup;
1576
    if (!(dom = virDomainObjListAdd(privconn->domains,
1577
                                    def,
1578
                                    privconn->xmlopt,
1579
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
1580 1581
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
1582 1583
        goto cleanup;
    def = NULL;
1584

1585 1586 1587 1588 1589
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_BOOTED) < 0) {
        if (!dom->persistent) {
            virDomainObjListRemove(privconn->domains, dom);
            dom = NULL;
        }
1590
        goto cleanup;
1591
    }
1592

1593
    event = virDomainEventLifecycleNewFromObj(dom,
1594 1595 1596
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);

1597
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1598
    if (ret)
1599
        ret->id = dom->def->id;
1600

1601
 cleanup:
1602
    if (dom)
1603
        virObjectUnlock(dom);
1604
    testObjectEventQueue(privconn, event);
1605
    virDomainDefFree(def);
1606
    testDriverUnlock(privconn);
1607
    return ret;
1608 1609 1610
}


1611
static virDomainPtr testDomainLookupByID(virConnectPtr conn,
1612
                                         int id)
1613
{
1614
    testDriverPtr privconn = conn->privateData;
1615 1616
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1617

1618
    if (!(dom = virDomainObjListFindByID(privconn->domains, id))) {
1619
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1620
        goto cleanup;
1621 1622
    }

1623
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1624 1625 1626
    if (ret)
        ret->id = dom->def->id;

1627
 cleanup:
1628
    if (dom)
1629
        virObjectUnlock(dom);
1630
    return ret;
1631 1632
}

1633
static virDomainPtr testDomainLookupByUUID(virConnectPtr conn,
1634
                                           const unsigned char *uuid)
1635
{
1636
    testDriverPtr privconn = conn->privateData;
1637
    virDomainPtr ret = NULL;
1638
    virDomainObjPtr dom;
1639

1640
    if (!(dom = virDomainObjListFindByUUID(privconn->domains, uuid))) {
1641
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1642
        goto cleanup;
1643
    }
1644

1645
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1646 1647 1648
    if (ret)
        ret->id = dom->def->id;

1649
 cleanup:
1650
    if (dom)
1651
        virObjectUnlock(dom);
1652
    return ret;
1653 1654
}

1655
static virDomainPtr testDomainLookupByName(virConnectPtr conn,
1656
                                           const char *name)
1657
{
1658
    testDriverPtr privconn = conn->privateData;
1659 1660
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1661

1662
    if (!(dom = virDomainObjListFindByName(privconn->domains, name))) {
1663
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1664
        goto cleanup;
1665
    }
1666

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

1671
 cleanup:
1672
    virDomainObjEndAPI(&dom);
1673
    return ret;
1674 1675
}

1676 1677 1678
static int testConnectListDomains(virConnectPtr conn,
                                  int *ids,
                                  int maxids)
1679
{
1680
    testDriverPtr privconn = conn->privateData;
1681

1682 1683
    return virDomainObjListGetActiveIDs(privconn->domains, ids, maxids,
                                        NULL, NULL);
1684 1685
}

1686
static int testDomainDestroy(virDomainPtr domain)
1687
{
1688
    testDriverPtr privconn = domain->conn->privateData;
1689
    virDomainObjPtr privdom;
1690
    virObjectEventPtr event = NULL;
1691
    int ret = -1;
1692 1693


1694
    if (!(privdom = testDomObjFromDomain(domain)))
1695
        goto cleanup;
1696

J
Jiri Denemark 已提交
1697
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_DESTROYED);
1698
    event = virDomainEventLifecycleNewFromObj(privdom,
1699 1700
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
1701

1702 1703
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
1704 1705

    ret = 0;
1706
 cleanup:
1707
    virDomainObjEndAPI(&privdom);
1708
    testObjectEventQueue(privconn, event);
1709
    return ret;
1710 1711
}

1712
static int testDomainResume(virDomainPtr domain)
1713
{
1714
    testDriverPtr privconn = domain->conn->privateData;
1715
    virDomainObjPtr privdom;
1716
    virObjectEventPtr event = NULL;
1717
    int ret = -1;
1718

1719 1720
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1721

J
Jiri Denemark 已提交
1722
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_PAUSED) {
1723 1724
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"),
                       domain->name);
1725
        goto cleanup;
1726
    }
1727

J
Jiri Denemark 已提交
1728 1729
    virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                         VIR_DOMAIN_RUNNING_UNPAUSED);
1730
    event = virDomainEventLifecycleNewFromObj(privdom,
1731 1732
                                     VIR_DOMAIN_EVENT_RESUMED,
                                     VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
1733 1734
    ret = 0;

1735
 cleanup:
1736
    virDomainObjEndAPI(&privdom);
1737
    testObjectEventQueue(privconn, event);
1738
    return ret;
1739 1740
}

1741
static int testDomainSuspend(virDomainPtr domain)
1742
{
1743
    testDriverPtr privconn = domain->conn->privateData;
1744
    virDomainObjPtr privdom;
1745
    virObjectEventPtr event = NULL;
1746
    int ret = -1;
J
Jiri Denemark 已提交
1747
    int state;
1748

1749 1750
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1751

J
Jiri Denemark 已提交
1752 1753
    state = virDomainObjGetState(privdom, NULL);
    if (state == VIR_DOMAIN_SHUTOFF || state == VIR_DOMAIN_PAUSED) {
1754 1755
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"),
                       domain->name);
1756
        goto cleanup;
1757
    }
1758

J
Jiri Denemark 已提交
1759
    virDomainObjSetState(privdom, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
1760
    event = virDomainEventLifecycleNewFromObj(privdom,
1761 1762
                                     VIR_DOMAIN_EVENT_SUSPENDED,
                                     VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
1763 1764
    ret = 0;

1765
 cleanup:
1766
    virDomainObjEndAPI(&privdom);
1767
    testObjectEventQueue(privconn, event);
1768
    return ret;
1769 1770
}

1771
static int testDomainShutdownFlags(virDomainPtr domain,
1772
                                   unsigned int flags)
1773
{
1774
    testDriverPtr privconn = domain->conn->privateData;
1775
    virDomainObjPtr privdom;
1776
    virObjectEventPtr event = NULL;
1777
    int ret = -1;
1778

1779 1780
    virCheckFlags(0, -1);

1781

1782
    if (!(privdom = testDomObjFromDomain(domain)))
1783
        goto cleanup;
1784

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

J
Jiri Denemark 已提交
1791
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1792
    event = virDomainEventLifecycleNewFromObj(privdom,
1793 1794
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1795

1796 1797
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
1798

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

1806
static int testDomainShutdown(virDomainPtr domain)
1807
{
1808
    return testDomainShutdownFlags(domain, 0);
1809 1810
}

1811
/* Similar behaviour as shutdown */
1812
static int testDomainReboot(virDomainPtr domain,
1813
                            unsigned int action ATTRIBUTE_UNUSED)
1814
{
1815
    testDriverPtr privconn = domain->conn->privateData;
1816
    virDomainObjPtr privdom;
1817
    virObjectEventPtr event = NULL;
1818
    int ret = -1;
1819 1820


1821
    if (!(privdom = testDomObjFromDomain(domain)))
1822
        goto cleanup;
1823

J
Jiri Denemark 已提交
1824 1825 1826
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTDOWN,
                         VIR_DOMAIN_SHUTDOWN_USER);

1827 1828
    switch (privdom->def->onReboot) {
    case VIR_DOMAIN_LIFECYCLE_DESTROY:
J
Jiri Denemark 已提交
1829 1830
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1831 1832
        break;

1833
    case VIR_DOMAIN_LIFECYCLE_RESTART:
J
Jiri Denemark 已提交
1834 1835
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
1836 1837
        break;

1838
    case VIR_DOMAIN_LIFECYCLE_PRESERVE:
J
Jiri Denemark 已提交
1839 1840
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1841 1842
        break;

1843
    case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME:
J
Jiri Denemark 已提交
1844 1845
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
1846
        break;
1847

1848
    default:
J
Jiri Denemark 已提交
1849 1850
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1851 1852
        break;
    }
1853

J
Jiri Denemark 已提交
1854 1855
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1856
        event = virDomainEventLifecycleNewFromObj(privdom,
1857 1858
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1859

1860 1861
        if (!privdom->persistent)
            virDomainObjListRemove(privconn->domains, privdom);
1862 1863
    }

1864
    ret = 0;
1865
 cleanup:
1866
    virDomainObjEndAPI(&privdom);
1867
    testObjectEventQueue(privconn, event);
1868
    return ret;
1869 1870
}

1871
static int testDomainGetInfo(virDomainPtr domain,
1872
                             virDomainInfoPtr info)
1873
{
1874
    struct timeval tv;
1875
    virDomainObjPtr privdom;
1876
    int ret = -1;
1877

1878 1879
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1880 1881

    if (gettimeofday(&tv, NULL) < 0) {
1882 1883
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("getting time of day"));
1884
        goto cleanup;
1885 1886
    }

J
Jiri Denemark 已提交
1887
    info->state = virDomainObjGetState(privdom, NULL);
1888
    info->memory = privdom->def->mem.cur_balloon;
1889
    info->maxMem = virDomainDefGetMemoryTotal(privdom->def);
1890
    info->nrVirtCpu = virDomainDefGetVcpus(privdom->def);
1891
    info->cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
1892 1893
    ret = 0;

1894
 cleanup:
1895
    virDomainObjEndAPI(&privdom);
1896
    return ret;
1897 1898
}

1899 1900 1901 1902 1903 1904 1905 1906 1907 1908
static int
testDomainGetState(virDomainPtr domain,
                   int *state,
                   int *reason,
                   unsigned int flags)
{
    virDomainObjPtr privdom;

    virCheckFlags(0, -1);

1909 1910
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1911

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

1914
    virDomainObjEndAPI(&privdom);
1915 1916

    return 0;
1917 1918
}

1919 1920
#define TEST_SAVE_MAGIC "TestGuestMagic"

1921 1922 1923
static int
testDomainSaveFlags(virDomainPtr domain, const char *path,
                    const char *dxml, unsigned int flags)
1924
{
1925
    testDriverPtr privconn = domain->conn->privateData;
1926 1927 1928
    char *xml = NULL;
    int fd = -1;
    int len;
1929
    virDomainObjPtr privdom;
1930
    virObjectEventPtr event = NULL;
1931
    int ret = -1;
1932

1933 1934
    virCheckFlags(0, -1);
    if (dxml) {
1935 1936
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1937 1938 1939
        return -1;
    }

1940

1941
    if (!(privdom = testDomObjFromDomain(domain)))
1942
        goto cleanup;
1943

1944
    xml = virDomainDefFormat(privdom->def, privconn->caps,
1945
                             VIR_DOMAIN_DEF_FORMAT_SECURE);
C
Cole Robinson 已提交
1946

1947
    if (xml == NULL) {
1948
        virReportSystemError(errno,
1949 1950
                             _("saving domain '%s' failed to allocate space for metadata"),
                             domain->name);
1951
        goto cleanup;
1952
    }
1953 1954

    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
1955
        virReportSystemError(errno,
1956 1957
                             _("saving domain '%s' to '%s': open failed"),
                             domain->name, path);
1958
        goto cleanup;
1959
    }
1960
    len = strlen(xml);
1961
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
1962
        virReportSystemError(errno,
1963 1964
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1965
        goto cleanup;
1966
    }
1967
    if (safewrite(fd, (char*)&len, sizeof(len)) < 0) {
1968
        virReportSystemError(errno,
1969 1970
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1971
        goto cleanup;
1972
    }
1973
    if (safewrite(fd, xml, len) < 0) {
1974
        virReportSystemError(errno,
1975 1976
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1977
        goto cleanup;
1978
    }
1979

1980
    if (VIR_CLOSE(fd) < 0) {
1981
        virReportSystemError(errno,
1982 1983
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1984
        goto cleanup;
1985
    }
1986 1987
    fd = -1;

J
Jiri Denemark 已提交
1988
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SAVED);
1989
    event = virDomainEventLifecycleNewFromObj(privdom,
1990 1991
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
1992

1993 1994
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
1995

1996
    ret = 0;
1997
 cleanup:
1998 1999 2000 2001 2002 2003
    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) {
2004
        VIR_FORCE_CLOSE(fd);
2005 2006
        unlink(path);
    }
2007
    virDomainObjEndAPI(&privdom);
2008
    testObjectEventQueue(privconn, event);
2009
    return ret;
2010 2011
}

2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023
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)
2024
{
2025
    testDriverPtr privconn = conn->privateData;
2026
    char *xml = NULL;
2027
    char magic[15];
2028 2029 2030
    int fd = -1;
    int len;
    virDomainDefPtr def = NULL;
2031
    virDomainObjPtr dom = NULL;
2032
    virObjectEventPtr event = NULL;
2033
    int ret = -1;
2034

2035 2036
    virCheckFlags(0, -1);
    if (dxml) {
2037 2038
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
2039 2040 2041
        return -1;
    }

2042
    if ((fd = open(path, O_RDONLY)) < 0) {
2043
        virReportSystemError(errno,
2044 2045
                             _("cannot read domain image '%s'"),
                             path);
2046
        goto cleanup;
2047
    }
2048
    if (saferead(fd, magic, sizeof(magic)) != sizeof(magic)) {
2049
        virReportSystemError(errno,
2050 2051
                             _("incomplete save header in '%s'"),
                             path);
2052
        goto cleanup;
2053
    }
2054
    if (memcmp(magic, TEST_SAVE_MAGIC, sizeof(magic))) {
2055 2056
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("mismatched header magic"));
2057
        goto cleanup;
2058
    }
2059
    if (saferead(fd, (char*)&len, sizeof(len)) != sizeof(len)) {
2060
        virReportSystemError(errno,
2061 2062
                             _("failed to read metadata length in '%s'"),
                             path);
2063
        goto cleanup;
2064 2065
    }
    if (len < 1 || len > 8192) {
2066 2067
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("length of metadata out of range"));
2068
        goto cleanup;
2069
    }
2070
    if (VIR_ALLOC_N(xml, len+1) < 0)
2071
        goto cleanup;
2072
    if (saferead(fd, xml, len) != len) {
2073
        virReportSystemError(errno,
2074
                             _("incomplete metadata in '%s'"), path);
2075
        goto cleanup;
2076 2077
    }
    xml[len] = '\0';
2078

2079
    def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
2080
                                  VIR_DOMAIN_DEF_PARSE_INACTIVE);
2081
    if (!def)
2082
        goto cleanup;
2083

2084
    if (testDomainGenerateIfnames(def) < 0)
2085
        goto cleanup;
2086
    if (!(dom = virDomainObjListAdd(privconn->domains,
2087
                                    def,
2088
                                    privconn->xmlopt,
2089 2090 2091
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
2092 2093
        goto cleanup;
    def = NULL;
2094

2095 2096 2097 2098 2099
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_RESTORED) < 0) {
        if (!dom->persistent) {
            virDomainObjListRemove(privconn->domains, dom);
            dom = NULL;
        }
2100
        goto cleanup;
2101
    }
2102

2103
    event = virDomainEventLifecycleNewFromObj(dom,
2104 2105
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
2106
    ret = 0;
2107

2108
 cleanup:
2109 2110
    virDomainDefFree(def);
    VIR_FREE(xml);
2111
    VIR_FORCE_CLOSE(fd);
2112
    if (dom)
2113
        virObjectUnlock(dom);
2114
    testObjectEventQueue(privconn, event);
2115
    return ret;
2116 2117
}

2118 2119 2120 2121 2122 2123 2124
static int
testDomainRestore(virConnectPtr conn,
                  const char *path)
{
    return testDomainRestoreFlags(conn, path, NULL, 0);
}

2125 2126 2127 2128
static int testDomainCoreDumpWithFormat(virDomainPtr domain,
                                        const char *to,
                                        unsigned int dumpformat,
                                        unsigned int flags)
2129
{
2130
    testDriverPtr privconn = domain->conn->privateData;
2131
    int fd = -1;
2132
    virDomainObjPtr privdom;
2133
    virObjectEventPtr event = NULL;
2134
    int ret = -1;
2135

E
Eric Blake 已提交
2136 2137
    virCheckFlags(VIR_DUMP_CRASH, -1);

2138

2139
    if (!(privdom = testDomObjFromDomain(domain)))
2140
        goto cleanup;
2141 2142

    if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
2143
        virReportSystemError(errno,
2144 2145
                             _("domain '%s' coredump: failed to open %s"),
                             domain->name, to);
2146
        goto cleanup;
2147
    }
2148
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
2149
        virReportSystemError(errno,
2150 2151
                             _("domain '%s' coredump: failed to write header to %s"),
                             domain->name, to);
2152
        goto cleanup;
2153
    }
2154
    if (VIR_CLOSE(fd) < 0) {
2155
        virReportSystemError(errno,
2156 2157
                             _("domain '%s' coredump: write failed: %s"),
                             domain->name, to);
2158
        goto cleanup;
2159
    }
2160

2161 2162 2163 2164 2165 2166 2167
    /* 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;
    }

2168
    if (flags & VIR_DUMP_CRASH) {
J
Jiri Denemark 已提交
2169
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_CRASHED);
2170
        event = virDomainEventLifecycleNewFromObj(privdom,
2171 2172
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
2173 2174
        if (!privdom->persistent)
            virDomainObjListRemove(privconn->domains, privdom);
2175
    }
2176

2177
    ret = 0;
2178
 cleanup:
2179
    VIR_FORCE_CLOSE(fd);
2180
    virDomainObjEndAPI(&privdom);
2181
    testObjectEventQueue(privconn, event);
2182
    return ret;
2183 2184
}

2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198

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)
{
2199 2200 2201
    char *ret;

    ignore_value(VIR_STRDUP(ret, "linux"));
2202
    return ret;
2203 2204
}

2205 2206 2207

static unsigned long long
testDomainGetMaxMemory(virDomainPtr domain)
2208
{
2209
    virDomainObjPtr privdom;
2210
    unsigned long long ret = 0;
2211

2212 2213
    if (!(privdom = testDomObjFromDomain(domain)))
        return 0;
2214

2215
    ret = virDomainDefGetMemoryTotal(privdom->def);
2216

2217
    virDomainObjEndAPI(&privdom);
2218
    return ret;
2219 2220
}

2221 2222
static int testDomainSetMaxMemory(virDomainPtr domain,
                                  unsigned long memory)
2223
{
2224 2225
    virDomainObjPtr privdom;

2226 2227
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2228 2229

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

2232
    virDomainObjEndAPI(&privdom);
2233
    return 0;
2234 2235
}

2236 2237
static int testDomainSetMemory(virDomainPtr domain,
                               unsigned long memory)
2238
{
2239
    virDomainObjPtr privdom;
2240
    int ret = -1;
2241

2242 2243
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2244

2245
    if (memory > virDomainDefGetMemoryTotal(privdom->def)) {
2246
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2247
        goto cleanup;
2248
    }
2249

2250
    privdom->def->mem.cur_balloon = memory;
2251 2252
    ret = 0;

2253
 cleanup:
2254
    virDomainObjEndAPI(&privdom);
2255
    return ret;
2256 2257
}

2258 2259
static int
testDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
C
Cole Robinson 已提交
2260
{
2261 2262 2263 2264
    virDomainObjPtr vm;
    virDomainDefPtr def;
    int ret = -1;

2265 2266
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2267 2268
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

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

2272
    if (!(def = virDomainObjGetOneDef(vm, flags)))
2273
        goto cleanup;
2274

2275 2276 2277
    if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
        ret = virDomainDefGetVcpusMax(def);
    else
2278
        ret = virDomainDefGetVcpus(def);
2279

2280
 cleanup:
2281
    virDomainObjEndAPI(&vm);
2282
    return ret;
C
Cole Robinson 已提交
2283 2284
}

2285 2286 2287
static int
testDomainGetMaxVcpus(virDomainPtr domain)
{
2288
    return testDomainGetVcpusFlags(domain, (VIR_DOMAIN_AFFECT_LIVE |
2289 2290 2291 2292 2293 2294 2295
                                            VIR_DOMAIN_VCPU_MAXIMUM));
}

static int
testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
                        unsigned int flags)
{
2296
    testDriverPtr driver = domain->conn->privateData;
2297
    virDomainObjPtr privdom = NULL;
2298
    virDomainDefPtr def;
2299
    virDomainDefPtr persistentDef;
C
Cole Robinson 已提交
2300 2301
    int ret = -1, maxvcpus;

2302 2303
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2304 2305
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

2306
    if ((maxvcpus = testConnectGetMaxVcpus(domain->conn, NULL)) < 0)
2307
        return -1;
2308 2309

    if (nrCpus > maxvcpus) {
2310
        virReportError(VIR_ERR_INVALID_ARG,
2311 2312
                       _("requested cpu amount exceeds maximum supported amount "
                         "(%d > %d)"), nrCpus, maxvcpus);
2313 2314
        return -1;
    }
2315

2316 2317
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2318

2319
    if (virDomainObjGetDefs(privdom, flags, &def, &persistentDef) < 0)
C
Cole Robinson 已提交
2320 2321
        goto cleanup;

2322
    if (def && virDomainDefGetVcpusMax(def) < nrCpus) {
2323 2324
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested cpu amount exceeds maximum (%d > %d)"),
2325
                       nrCpus, virDomainDefGetVcpusMax(def));
2326
        goto cleanup;
2327
    }
2328

2329 2330
    if (persistentDef &&
        !(flags & VIR_DOMAIN_VCPU_MAXIMUM) &&
2331
        virDomainDefGetVcpusMax(persistentDef) < nrCpus) {
2332 2333
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested cpu amount exceeds maximum (%d > %d)"),
2334
                       nrCpus, virDomainDefGetVcpusMax(persistentDef));
2335
        goto cleanup;
2336
    }
2337

2338 2339 2340
    if (def &&
        virDomainDefSetVcpus(def, nrCpus) < 0)
        goto cleanup;
2341

2342 2343
    if (persistentDef) {
        if (flags & VIR_DOMAIN_VCPU_MAXIMUM) {
2344 2345
            if (virDomainDefSetVcpusMax(persistentDef, nrCpus,
                                        driver->xmlopt) < 0)
2346
                goto cleanup;
2347
        } else {
2348 2349
            if (virDomainDefSetVcpus(persistentDef, nrCpus) < 0)
                goto cleanup;
2350
        }
2351
    }
2352

2353 2354
    ret = 0;

2355
 cleanup:
2356
    virDomainObjEndAPI(&privdom);
2357
    return ret;
2358 2359
}

2360
static int
2361
testDomainSetVcpus(virDomainPtr domain, unsigned int nrCpus)
2362
{
2363
    return testDomainSetVcpusFlags(domain, nrCpus, VIR_DOMAIN_AFFECT_LIVE);
2364 2365
}

C
Cole Robinson 已提交
2366 2367 2368 2369 2370 2371
static int testDomainGetVcpus(virDomainPtr domain,
                              virVcpuInfoPtr info,
                              int maxinfo,
                              unsigned char *cpumaps,
                              int maplen)
{
2372
    testDriverPtr privconn = domain->conn->privateData;
C
Cole Robinson 已提交
2373
    virDomainObjPtr privdom;
2374
    virDomainDefPtr def;
2375
    size_t i;
2376
    int maxcpu, hostcpus;
C
Cole Robinson 已提交
2377 2378 2379
    int ret = -1;
    struct timeval tv;
    unsigned long long statbase;
2380
    virBitmapPtr allcpumap = NULL;
C
Cole Robinson 已提交
2381

2382 2383
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
C
Cole Robinson 已提交
2384 2385

    if (!virDomainObjIsActive(privdom)) {
2386
        virReportError(VIR_ERR_OPERATION_INVALID,
2387
                       "%s", _("cannot list vcpus for an inactive domain"));
C
Cole Robinson 已提交
2388 2389 2390
        goto cleanup;
    }

2391
    def = privdom->def;
C
Cole Robinson 已提交
2392 2393

    if (gettimeofday(&tv, NULL) < 0) {
2394
        virReportSystemError(errno,
C
Cole Robinson 已提交
2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405
                             "%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;

2406 2407 2408 2409 2410
    if (!(allcpumap = virBitmapNew(hostcpus)))
        goto cleanup;

    virBitmapSetAll(allcpumap);

C
Cole Robinson 已提交
2411
    /* Clamp to actual number of vcpus */
2412 2413
    if (maxinfo > virDomainDefGetVcpus(privdom->def))
        maxinfo = virDomainDefGetVcpus(privdom->def);
C
Cole Robinson 已提交
2414

2415 2416
    memset(info, 0, sizeof(*info) * maxinfo);
    memset(cpumaps, 0, maxinfo * maplen);
C
Cole Robinson 已提交
2417

2418
    for (i = 0; i < maxinfo; i++) {
2419
        virDomainVcpuDefPtr vcpu = virDomainDefGetVcpu(def, i);
2420
        virBitmapPtr bitmap = NULL;
C
Cole Robinson 已提交
2421

2422 2423
        if (!vcpu->online)
            continue;
C
Cole Robinson 已提交
2424

2425 2426
        if (vcpu->cpumask)
            bitmap = vcpu->cpumask;
2427 2428 2429 2430
        else if (def->cpumask)
            bitmap = def->cpumask;
        else
            bitmap = allcpumap;
C
Cole Robinson 已提交
2431

2432 2433
        if (cpumaps)
            virBitmapToDataBuf(bitmap, VIR_GET_CPUMAP(cpumaps, maplen, i), maplen);
C
Cole Robinson 已提交
2434

2435 2436 2437
        info[i].number = i;
        info[i].state = VIR_VCPU_RUNNING;
        info[i].cpu = virBitmapLastSetBit(bitmap);
C
Cole Robinson 已提交
2438

2439 2440
        /* Fake an increasing cpu time value */
        info[i].cpuTime = statbase / 10;
C
Cole Robinson 已提交
2441 2442 2443
    }

    ret = maxinfo;
2444
 cleanup:
2445
    virBitmapFree(allcpumap);
2446
    virDomainObjEndAPI(&privdom);
C
Cole Robinson 已提交
2447 2448 2449
    return ret;
}

C
Cole Robinson 已提交
2450 2451 2452 2453 2454
static int testDomainPinVcpu(virDomainPtr domain,
                             unsigned int vcpu,
                             unsigned char *cpumap,
                             int maplen)
{
2455
    virDomainVcpuDefPtr vcpuinfo;
C
Cole Robinson 已提交
2456
    virDomainObjPtr privdom;
2457
    virDomainDefPtr def;
C
Cole Robinson 已提交
2458 2459
    int ret = -1;

2460 2461
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
C
Cole Robinson 已提交
2462

2463 2464
    def = privdom->def;

C
Cole Robinson 已提交
2465
    if (!virDomainObjIsActive(privdom)) {
2466
        virReportError(VIR_ERR_OPERATION_INVALID,
2467
                       "%s", _("cannot pin vcpus on an inactive domain"));
C
Cole Robinson 已提交
2468 2469 2470
        goto cleanup;
    }

2471 2472
    if (!(vcpuinfo = virDomainDefGetVcpu(def, vcpu)) ||
        !vcpuinfo->online) {
2473 2474 2475
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested vcpu '%d' is not present in the domain"),
                       vcpu);
C
Cole Robinson 已提交
2476 2477 2478
        goto cleanup;
    }

2479 2480 2481
    virBitmapFree(vcpuinfo->cpumask);

    if (!(vcpuinfo->cpumask = virBitmapNewData(cpumap, maplen)))
2482
        goto cleanup;
C
Cole Robinson 已提交
2483 2484

    ret = 0;
2485

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

2491 2492 2493 2494 2495 2496 2497
static int
testDomainGetVcpuPinInfo(virDomainPtr dom,
                        int ncpumaps,
                        unsigned char *cpumaps,
                        int maplen,
                        unsigned int flags)
{
2498
    testDriverPtr driver = dom->conn->privateData;
2499 2500
    virDomainObjPtr privdom;
    virDomainDefPtr def;
2501
    int ret = -1;
2502 2503 2504 2505 2506 2507 2508

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

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

2509 2510 2511
    ret = virDomainDefGetVcpuPinInfoHelper(def, maplen, ncpumaps, cpumaps,
                                           VIR_NODEINFO_MAXCPUS(driver->nodeInfo),
                                           NULL);
2512 2513 2514 2515 2516 2517

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

2518
static char *testDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
2519
{
2520
    testDriverPtr privconn = domain->conn->privateData;
2521
    virDomainDefPtr def;
2522
    virDomainObjPtr privdom;
2523 2524
    char *ret = NULL;

2525 2526
    /* Flags checked by virDomainDefFormat */

2527 2528
    if (!(privdom = testDomObjFromDomain(domain)))
        return NULL;
2529

2530 2531
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
2532

2533 2534
    ret = virDomainDefFormat(def, privconn->caps,
                             virDomainDefFormatConvertXMLFlags(flags));
2535

2536
    virDomainObjEndAPI(&privdom);
2537
    return ret;
2538
}
2539

2540 2541
static int testConnectNumOfDefinedDomains(virConnectPtr conn)
{
2542
    testDriverPtr privconn = conn->privateData;
2543

2544
    return virDomainObjListNumOfDomains(privconn->domains, false, NULL, NULL);
2545 2546
}

2547 2548
static int testConnectListDefinedDomains(virConnectPtr conn,
                                         char **const names,
2549 2550
                                         int maxnames)
{
2551

2552
    testDriverPtr privconn = conn->privateData;
2553 2554

    memset(names, 0, sizeof(*names)*maxnames);
2555 2556
    return virDomainObjListGetInactiveNames(privconn->domains, names, maxnames,
                                            NULL, NULL);
2557 2558
}

2559 2560 2561
static virDomainPtr testDomainDefineXMLFlags(virConnectPtr conn,
                                             const char *xml,
                                             unsigned int flags)
2562
{
2563
    testDriverPtr privconn = conn->privateData;
2564
    virDomainPtr ret = NULL;
2565
    virDomainDefPtr def;
2566
    virDomainObjPtr dom = NULL;
2567
    virObjectEventPtr event = NULL;
2568
    virDomainDefPtr oldDef = NULL;
2569 2570 2571
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;

    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
2572

2573
    if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
2574
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
2575

2576
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
2577
                                       parse_flags)) == NULL)
2578
        goto cleanup;
2579

2580
    if (testDomainGenerateIfnames(def) < 0)
2581
        goto cleanup;
2582
    if (!(dom = virDomainObjListAdd(privconn->domains,
2583
                                    def,
2584
                                    privconn->xmlopt,
2585 2586
                                    0,
                                    &oldDef)))
2587
        goto cleanup;
2588
    def = NULL;
2589
    dom->persistent = 1;
2590

2591
    event = virDomainEventLifecycleNewFromObj(dom,
2592
                                     VIR_DOMAIN_EVENT_DEFINED,
2593
                                     !oldDef ?
2594 2595
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
2596

2597
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
2598
    if (ret)
2599
        ret->id = dom->def->id;
2600

2601
 cleanup:
2602
    virDomainDefFree(def);
2603
    virDomainDefFree(oldDef);
2604
    if (dom)
2605
        virObjectUnlock(dom);
2606
    testObjectEventQueue(privconn, event);
2607
    return ret;
2608 2609
}

2610 2611 2612 2613 2614 2615
static virDomainPtr
testDomainDefineXML(virConnectPtr conn, const char *xml)
{
    return testDomainDefineXMLFlags(conn, xml, 0);
}

2616 2617 2618 2619 2620 2621
static char *testDomainGetMetadata(virDomainPtr dom,
                                   int type,
                                   const char *uri,
                                   unsigned int flags)
{
    virDomainObjPtr privdom;
2622
    char *ret;
2623 2624 2625 2626

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, NULL);

2627 2628
    if (!(privdom = testDomObjFromDomain(dom)))
        return NULL;
2629

2630
    ret = virDomainObjGetMetadata(privdom, type, uri, flags);
2631

2632
    virDomainObjEndAPI(&privdom);
2633 2634 2635 2636 2637 2638 2639 2640 2641 2642
    return ret;
}

static int testDomainSetMetadata(virDomainPtr dom,
                                 int type,
                                 const char *metadata,
                                 const char *key,
                                 const char *uri,
                                 unsigned int flags)
{
2643
    testDriverPtr privconn = dom->conn->privateData;
2644
    virDomainObjPtr privdom;
2645
    int ret;
2646 2647 2648 2649

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

2650 2651
    if (!(privdom = testDomObjFromDomain(dom)))
        return -1;
2652 2653 2654

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

2657
    virDomainObjEndAPI(&privdom);
2658 2659 2660 2661
    return ret;
}


2662 2663
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
2664 2665
                                      int startCell, int maxCells)
{
2666
    testDriverPtr privconn = conn->privateData;
2667 2668
    int cell;
    size_t i;
2669
    int ret = -1;
2670

2671
    testDriverLock(privconn);
2672
    if (startCell > privconn->numCells) {
2673 2674
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("Range exceeds available cells"));
2675
        goto cleanup;
2676 2677
    }

2678 2679 2680 2681
    for (cell = startCell, i = 0;
         (cell < privconn->numCells && i < maxCells);
         ++cell, ++i) {
        freemems[i] = privconn->cells[cell].mem;
2682
    }
2683
    ret = i;
2684

2685
 cleanup:
2686
    testDriverUnlock(privconn);
2687
    return ret;
2688 2689 2690
}


2691 2692
static int testDomainCreateWithFlags(virDomainPtr domain, unsigned int flags)
{
2693
    testDriverPtr privconn = domain->conn->privateData;
2694
    virDomainObjPtr privdom;
2695
    virObjectEventPtr event = NULL;
2696
    int ret = -1;
2697

2698 2699
    virCheckFlags(0, -1);

2700
    testDriverLock(privconn);
2701

2702
    if (!(privdom = testDomObjFromDomain(domain)))
2703
        goto cleanup;
2704

J
Jiri Denemark 已提交
2705
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_SHUTOFF) {
2706 2707
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Domain '%s' is already running"), domain->name);
2708
        goto cleanup;
2709 2710
    }

2711
    if (testDomainStartState(privconn, privdom,
J
Jiri Denemark 已提交
2712
                             VIR_DOMAIN_RUNNING_BOOTED) < 0)
2713 2714 2715
        goto cleanup;
    domain->id = privdom->def->id;

2716
    event = virDomainEventLifecycleNewFromObj(privdom,
2717 2718
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
2719
    ret = 0;
2720

2721
 cleanup:
2722
    virDomainObjEndAPI(&privdom);
2723
    testObjectEventQueue(privconn, event);
2724
    testDriverUnlock(privconn);
2725
    return ret;
2726 2727
}

2728 2729
static int testDomainCreate(virDomainPtr domain)
{
2730 2731 2732
    return testDomainCreateWithFlags(domain, 0);
}

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

2742 2743
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
                  VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
2744

2745

2746
    if (!(privdom = testDomObjFromDomain(domain)))
2747
        goto cleanup;
2748

C
Cole Robinson 已提交
2749 2750 2751 2752 2753 2754 2755 2756
    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;
    }

2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774
    /* 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. */
    }

2775
    event = virDomainEventLifecycleNewFromObj(privdom,
2776 2777
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
C
Cole Robinson 已提交
2778 2779
    privdom->hasManagedSave = false;

2780
    if (virDomainObjIsActive(privdom))
2781
        privdom->persistent = 0;
2782 2783
    else
        virDomainObjListRemove(privconn->domains, privdom);
2784

2785
    ret = 0;
2786

2787
 cleanup:
2788
    virDomainObjEndAPI(&privdom);
2789
    testObjectEventQueue(privconn, event);
2790
    return ret;
2791 2792
}

2793 2794 2795 2796 2797
static int testDomainUndefine(virDomainPtr domain)
{
    return testDomainUndefineFlags(domain, 0);
}

2798 2799 2800
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
2801 2802
    virDomainObjPtr privdom;

2803 2804
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2805

2806
    *autostart = privdom->autostart;
2807

2808
    virDomainObjEndAPI(&privdom);
2809
    return 0;
2810 2811 2812 2813 2814 2815
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
2816 2817
    virDomainObjPtr privdom;

2818 2819
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2820

2821
    privdom->autostart = autostart ? 1 : 0;
2822

2823
    virDomainObjEndAPI(&privdom);
2824
    return 0;
2825
}
2826

2827
static char *testDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED,
2828 2829
                                        int *nparams)
{
2830 2831
    char *type = NULL;

2832 2833 2834
    if (nparams)
        *nparams = 1;

2835
    ignore_value(VIR_STRDUP(type, "fair"));
2836

2837 2838 2839
    return type;
}

2840
static int
2841 2842 2843 2844
testDomainGetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int *nparams,
                                      unsigned int flags)
2845
{
2846
    virDomainObjPtr privdom;
2847
    int ret = -1;
2848

2849 2850
    virCheckFlags(0, -1);

2851 2852
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2853

2854 2855
    if (virTypedParameterAssign(params, VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, 50) < 0)
2856
        goto cleanup;
2857 2858
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
2859 2860

    *nparams = 1;
2861 2862
    ret = 0;

2863
 cleanup:
2864
    virDomainObjEndAPI(&privdom);
2865
    return ret;
2866
}
2867

2868
static int
2869 2870 2871
testDomainGetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int *nparams)
2872
{
2873
    return testDomainGetSchedulerParametersFlags(domain, params, nparams, 0);
2874
}
2875

2876
static int
2877 2878 2879 2880
testDomainSetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int nparams,
                                      unsigned int flags)
2881
{
2882
    virDomainObjPtr privdom;
2883 2884
    int ret = -1;
    size_t i;
2885

2886
    virCheckFlags(0, -1);
2887 2888 2889 2890
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
2891
        return -1;
2892

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

2896
    for (i = 0; i < nparams; i++) {
2897 2898 2899
        if (STREQ(params[i].field, VIR_DOMAIN_SCHEDULER_WEIGHT)) {
            /* XXX */
            /*privdom->weight = params[i].value.ui;*/
2900
        }
2901
    }
2902

2903 2904
    ret = 0;

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

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

2917 2918
static int testDomainBlockStats(virDomainPtr domain,
                                const char *path,
2919
                                virDomainBlockStatsPtr stats)
2920 2921 2922 2923
{
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
2924
    int ret = -1;
2925

2926 2927 2928 2929 2930 2931
    if (!*path) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("summary statistics are not supported yet"));
        return ret;
    }

2932 2933
    if (!(privdom = testDomObjFromDomain(domain)))
        return ret;
2934

2935
    if (virDomainDiskIndexByName(privdom->def, path, false) < 0) {
2936 2937
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path: %s"), path);
2938 2939 2940 2941
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
2942
        virReportSystemError(errno,
2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955
                             "%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;
2956
 error:
2957
    virDomainObjEndAPI(&privdom);
2958 2959 2960 2961 2962
    return ret;
}

static int testDomainInterfaceStats(virDomainPtr domain,
                                    const char *path,
2963
                                    virDomainInterfaceStatsPtr stats)
2964 2965 2966 2967
{
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
2968 2969
    size_t i;
    int found = 0, ret = -1;
2970

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

2974
    for (i = 0; i < privdom->def->nnets; i++) {
2975
        if (privdom->def->nets[i]->ifname &&
2976
            STREQ(privdom->def->nets[i]->ifname, path)) {
2977 2978 2979 2980 2981 2982
            found = 1;
            break;
        }
    }

    if (!found) {
2983 2984
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path, '%s' is not a known interface"), path);
2985 2986 2987 2988
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
2989
        virReportSystemError(errno,
2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005
                             "%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;
3006
 error:
3007
    virDomainObjEndAPI(&privdom);
3008 3009 3010
    return ret;
}

3011

3012 3013
static virNetworkPtr testNetworkLookupByUUID(virConnectPtr conn,
                                             const unsigned char *uuid)
3014
{
3015
    testDriverPtr privconn = conn->privateData;
3016
    virNetworkObjPtr net;
3017
    virNetworkPtr ret = NULL;
3018

3019
    net = virNetworkObjFindByUUID(privconn->networks, uuid);
3020
    if (net == NULL) {
3021
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3022
        goto cleanup;
3023 3024
    }

3025 3026
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

3027
 cleanup:
3028
    virNetworkObjEndAPI(&net);
3029
    return ret;
3030
}
3031

3032
static virNetworkPtr testNetworkLookupByName(virConnectPtr conn,
3033
                                             const char *name)
3034
{
3035
    testDriverPtr privconn = conn->privateData;
3036 3037
    virNetworkObjPtr net;
    virNetworkPtr ret = NULL;
3038

3039
    net = virNetworkObjFindByName(privconn->networks, name);
3040
    if (net == NULL) {
3041
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3042
        goto cleanup;
3043 3044
    }

3045 3046
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

3047
 cleanup:
3048
    virNetworkObjEndAPI(&net);
3049
    return ret;
3050 3051 3052
}


3053 3054
static int testConnectNumOfNetworks(virConnectPtr conn)
{
3055
    testDriverPtr privconn = conn->privateData;
3056
    int numActive;
3057

3058 3059
    numActive = virNetworkObjListNumOfNetworks(privconn->networks,
                                               true, NULL, conn);
3060
    return numActive;
3061 3062
}

3063
static int testConnectListNetworks(virConnectPtr conn, char **const names, int nnames) {
3064
    testDriverPtr privconn = conn->privateData;
3065
    int n;
3066

3067 3068
    n = virNetworkObjListGetNames(privconn->networks,
                                  true, names, nnames, NULL, conn);
3069
    return n;
3070 3071
}

3072 3073
static int testConnectNumOfDefinedNetworks(virConnectPtr conn)
{
3074
    testDriverPtr privconn = conn->privateData;
3075
    int numInactive;
3076

3077 3078
    numInactive = virNetworkObjListNumOfNetworks(privconn->networks,
                                                 false, NULL, conn);
3079
    return numInactive;
3080 3081
}

3082
static int testConnectListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
3083
    testDriverPtr privconn = conn->privateData;
3084
    int n;
3085

3086 3087
    n = virNetworkObjListGetNames(privconn->networks,
                                  false, names, nnames, NULL, conn);
3088
    return n;
3089 3090
}

3091
static int
3092
testConnectListAllNetworks(virConnectPtr conn,
3093 3094 3095
                           virNetworkPtr **nets,
                           unsigned int flags)
{
3096
    testDriverPtr privconn = conn->privateData;
3097 3098 3099

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

3100
    return virNetworkObjListExport(conn, privconn->networks, nets, NULL, flags);
3101
}
3102 3103 3104

static int testNetworkIsActive(virNetworkPtr net)
{
3105
    testDriverPtr privconn = net->conn->privateData;
3106 3107 3108
    virNetworkObjPtr obj;
    int ret = -1;

3109
    obj = virNetworkObjFindByUUID(privconn->networks, net->uuid);
3110
    if (!obj) {
3111
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3112 3113 3114 3115
        goto cleanup;
    }
    ret = virNetworkObjIsActive(obj);

3116
 cleanup:
3117
    virNetworkObjEndAPI(&obj);
3118 3119 3120 3121 3122
    return ret;
}

static int testNetworkIsPersistent(virNetworkPtr net)
{
3123
    testDriverPtr privconn = net->conn->privateData;
3124 3125 3126
    virNetworkObjPtr obj;
    int ret = -1;

3127
    obj = virNetworkObjFindByUUID(privconn->networks, net->uuid);
3128
    if (!obj) {
3129
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3130 3131 3132 3133
        goto cleanup;
    }
    ret = obj->persistent;

3134
 cleanup:
3135
    virNetworkObjEndAPI(&obj);
3136 3137 3138 3139
    return ret;
}


3140 3141
static virNetworkPtr testNetworkCreateXML(virConnectPtr conn, const char *xml)
{
3142
    testDriverPtr privconn = conn->privateData;
3143
    virNetworkDefPtr def;
3144
    virNetworkObjPtr net = NULL;
3145
    virNetworkPtr ret = NULL;
3146
    virObjectEventPtr event = NULL;
3147

3148
    if ((def = virNetworkDefParseString(xml)) == NULL)
3149
        goto cleanup;
3150

3151 3152 3153
    if (!(net = virNetworkAssignDef(privconn->networks, def,
                                    VIR_NETWORK_OBJ_LIST_ADD_LIVE |
                                    VIR_NETWORK_OBJ_LIST_ADD_CHECK_LIVE)))
3154 3155
        goto cleanup;
    def = NULL;
3156
    net->active = 1;
3157

3158
    event = virNetworkEventLifecycleNew(net->def->name, net->def->uuid,
3159 3160
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3161

3162
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3163

3164
 cleanup:
3165
    virNetworkDefFree(def);
3166
    testObjectEventQueue(privconn, event);
3167
    virNetworkObjEndAPI(&net);
3168
    return ret;
3169 3170
}

3171
static
3172
virNetworkPtr testNetworkDefineXML(virConnectPtr conn, const char *xml)
3173
{
3174
    testDriverPtr privconn = conn->privateData;
3175
    virNetworkDefPtr def;
3176
    virNetworkObjPtr net = NULL;
3177
    virNetworkPtr ret = NULL;
3178
    virObjectEventPtr event = NULL;
3179

3180
    if ((def = virNetworkDefParseString(xml)) == NULL)
3181
        goto cleanup;
3182

3183
    if (!(net = virNetworkAssignDef(privconn->networks, def, 0)))
3184 3185
        goto cleanup;
    def = NULL;
3186

3187
    event = virNetworkEventLifecycleNew(net->def->name, net->def->uuid,
3188 3189
                                        VIR_NETWORK_EVENT_DEFINED,
                                        0);
3190

3191
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3192

3193
 cleanup:
3194
    virNetworkDefFree(def);
3195
    testObjectEventQueue(privconn, event);
3196
    virNetworkObjEndAPI(&net);
3197
    return ret;
3198 3199
}

3200 3201
static int testNetworkUndefine(virNetworkPtr network)
{
3202
    testDriverPtr privconn = network->conn->privateData;
3203
    virNetworkObjPtr privnet;
3204
    int ret = -1;
3205
    virObjectEventPtr event = NULL;
3206

3207
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3208 3209

    if (privnet == NULL) {
3210
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3211
        goto cleanup;
3212
    }
3213

D
Daniel P. Berrange 已提交
3214
    if (virNetworkObjIsActive(privnet)) {
3215 3216
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is still running"), network->name);
3217
        goto cleanup;
3218 3219
    }

3220
    event = virNetworkEventLifecycleNew(network->name, network->uuid,
3221 3222
                                        VIR_NETWORK_EVENT_UNDEFINED,
                                        0);
3223

3224
    virNetworkRemoveInactive(privconn->networks, privnet);
3225
    ret = 0;
3226

3227
 cleanup:
3228
    testObjectEventQueue(privconn, event);
3229
    virNetworkObjEndAPI(&privnet);
3230
    return ret;
3231 3232
}

3233 3234 3235 3236 3237 3238 3239 3240
static int
testNetworkUpdate(virNetworkPtr net,
                  unsigned int command,
                  unsigned int section,
                  int parentIndex,
                  const char *xml,
                  unsigned int flags)
{
3241
    testDriverPtr privconn = net->conn->privateData;
3242 3243 3244 3245 3246 3247 3248
    virNetworkObjPtr network = NULL;
    int isActive, ret = -1;

    virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
                  VIR_NETWORK_UPDATE_AFFECT_CONFIG,
                  -1);

3249
    network = virNetworkObjFindByUUID(privconn->networks, net->uuid);
3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273
    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;
3274
 cleanup:
3275
    virNetworkObjEndAPI(&network);
3276 3277 3278
    return ret;
}

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

3286
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3287
    if (privnet == NULL) {
3288
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3289
        goto cleanup;
3290
    }
3291

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

3298
    privnet->active = 1;
3299
    event = virNetworkEventLifecycleNew(privnet->def->name, privnet->def->uuid,
3300 3301
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3302
    ret = 0;
3303

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

3310 3311
static int testNetworkDestroy(virNetworkPtr network)
{
3312
    testDriverPtr privconn = network->conn->privateData;
3313
    virNetworkObjPtr privnet;
3314
    int ret = -1;
3315
    virObjectEventPtr event = NULL;
3316

3317
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3318
    if (privnet == NULL) {
3319
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3320
        goto cleanup;
3321
    }
3322

3323
    privnet->active = 0;
3324
    event = virNetworkEventLifecycleNew(privnet->def->name, privnet->def->uuid,
3325 3326
                                        VIR_NETWORK_EVENT_STOPPED,
                                        0);
3327
    if (!privnet->persistent)
3328
        virNetworkRemoveInactive(privconn->networks, privnet);
3329

3330 3331
    ret = 0;

3332
 cleanup:
3333
    testObjectEventQueue(privconn, event);
3334
    virNetworkObjEndAPI(&privnet);
3335
    return ret;
3336 3337
}

3338
static char *testNetworkGetXMLDesc(virNetworkPtr network,
E
Eric Blake 已提交
3339
                                   unsigned int flags)
3340
{
3341
    testDriverPtr privconn = network->conn->privateData;
3342
    virNetworkObjPtr privnet;
3343
    char *ret = NULL;
3344

E
Eric Blake 已提交
3345 3346
    virCheckFlags(0, NULL);

3347
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3348
    if (privnet == NULL) {
3349
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3350
        goto cleanup;
3351
    }
3352

3353
    ret = virNetworkDefFormat(privnet->def, flags);
3354

3355
 cleanup:
3356
    virNetworkObjEndAPI(&privnet);
3357
    return ret;
3358 3359 3360
}

static char *testNetworkGetBridgeName(virNetworkPtr network) {
3361
    testDriverPtr privconn = network->conn->privateData;
3362
    char *bridge = NULL;
3363 3364
    virNetworkObjPtr privnet;

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

3371
    if (!(privnet->def->bridge)) {
3372 3373 3374
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("network '%s' does not have a bridge name."),
                       privnet->def->name);
3375 3376 3377
        goto cleanup;
    }

3378
    ignore_value(VIR_STRDUP(bridge, privnet->def->bridge));
3379

3380
 cleanup:
3381
    virNetworkObjEndAPI(&privnet);
3382 3383 3384 3385
    return bridge;
}

static int testNetworkGetAutostart(virNetworkPtr network,
3386 3387
                                   int *autostart)
{
3388
    testDriverPtr privconn = network->conn->privateData;
3389
    virNetworkObjPtr privnet;
3390
    int ret = -1;
3391

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

3398
    *autostart = privnet->autostart;
3399 3400
    ret = 0;

3401
 cleanup:
3402
    virNetworkObjEndAPI(&privnet);
3403
    return ret;
3404 3405 3406
}

static int testNetworkSetAutostart(virNetworkPtr network,
3407 3408
                                   int autostart)
{
3409
    testDriverPtr privconn = network->conn->privateData;
3410
    virNetworkObjPtr privnet;
3411
    int ret = -1;
3412

3413
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3414
    if (privnet == NULL) {
3415
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3416
        goto cleanup;
3417 3418
    }

3419
    privnet->autostart = autostart ? 1 : 0;
3420 3421
    ret = 0;

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

C
Cole Robinson 已提交
3427

L
Laine Stump 已提交
3428 3429 3430 3431 3432
/*
 * Physical host interface routines
 */


3433
static int testConnectNumOfInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3434
{
3435
    testDriverPtr privconn = conn->privateData;
3436 3437
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3438 3439

    testDriverLock(privconn);
3440
    for (i = 0; (i < privconn->ifaces.count); i++) {
L
Laine Stump 已提交
3441
        virInterfaceObjLock(privconn->ifaces.objs[i]);
3442
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i]))
L
Laine Stump 已提交
3443 3444 3445 3446 3447 3448 3449
            count++;
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3450
static int testConnectListInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3451
{
3452
    testDriverPtr privconn = conn->privateData;
3453 3454
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3455 3456 3457

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
3458
    for (i = 0; (i < privconn->ifaces.count) && (n < nnames); i++) {
L
Laine Stump 已提交
3459
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3460
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
3461
            if (VIR_STRDUP(names[n++], privconn->ifaces.objs[i]->def->name) < 0) {
L
Laine Stump 已提交
3462
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
3463
                goto error;
L
Laine Stump 已提交
3464 3465 3466 3467 3468 3469 3470 3471
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

3472
 error:
3473
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3474 3475 3476 3477 3478
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

3479
static int testConnectNumOfDefinedInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3480
{
3481
    testDriverPtr privconn = conn->privateData;
3482 3483
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3484 3485

    testDriverLock(privconn);
3486
    for (i = 0; i < privconn->ifaces.count; i++) {
L
Laine Stump 已提交
3487
        virInterfaceObjLock(privconn->ifaces.objs[i]);
3488
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i]))
L
Laine Stump 已提交
3489 3490 3491 3492 3493 3494 3495
            count++;
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3496
static int testConnectListDefinedInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3497
{
3498
    testDriverPtr privconn = conn->privateData;
3499 3500
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3501 3502 3503

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

    return n;

3518
 error:
3519
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3520 3521 3522 3523 3524
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

3525
static virInterfacePtr testInterfaceLookupByName(virConnectPtr conn,
L
Laine Stump 已提交
3526 3527
                                                 const char *name)
{
3528
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3529 3530 3531 3532 3533 3534 3535 3536
    virInterfaceObjPtr iface;
    virInterfacePtr ret = NULL;

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

    if (iface == NULL) {
3537
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3538 3539 3540 3541 3542
        goto cleanup;
    }

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

3543
 cleanup:
L
Laine Stump 已提交
3544 3545 3546 3547 3548
    if (iface)
        virInterfaceObjUnlock(iface);
    return ret;
}

3549
static virInterfacePtr testInterfaceLookupByMACString(virConnectPtr conn,
L
Laine Stump 已提交
3550 3551
                                                      const char *mac)
{
3552
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3553 3554 3555 3556 3557 3558 3559 3560 3561
    virInterfaceObjPtr iface;
    int ifacect;
    virInterfacePtr ret = NULL;

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

    if (ifacect == 0) {
3562
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3563 3564 3565 3566
        goto cleanup;
    }

    if (ifacect > 1) {
3567
        virReportError(VIR_ERR_MULTIPLE_INTERFACES, NULL);
L
Laine Stump 已提交
3568 3569 3570 3571 3572
        goto cleanup;
    }

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

3573
 cleanup:
L
Laine Stump 已提交
3574 3575 3576 3577 3578
    if (iface)
        virInterfaceObjUnlock(iface);
    return ret;
}

3579 3580
static int testInterfaceIsActive(virInterfacePtr iface)
{
3581
    testDriverPtr privconn = iface->conn->privateData;
3582 3583 3584 3585 3586 3587 3588
    virInterfaceObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virInterfaceFindByName(&privconn->ifaces, iface->name);
    testDriverUnlock(privconn);
    if (!obj) {
3589
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
3590 3591 3592 3593
        goto cleanup;
    }
    ret = virInterfaceObjIsActive(obj);

3594
 cleanup:
3595 3596 3597 3598 3599
    if (obj)
        virInterfaceObjUnlock(obj);
    return ret;
}

3600
static int testInterfaceChangeBegin(virConnectPtr conn,
E
Eric Blake 已提交
3601
                                    unsigned int flags)
3602
{
3603
    testDriverPtr privconn = conn->privateData;
3604 3605
    int ret = -1;

E
Eric Blake 已提交
3606 3607
    virCheckFlags(0, -1);

3608 3609
    testDriverLock(privconn);
    if (privconn->transaction_running) {
3610
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3611
                       _("there is another transaction running."));
3612 3613 3614 3615 3616 3617 3618 3619 3620 3621
        goto cleanup;
    }

    privconn->transaction_running = true;

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

    ret = 0;
3622
 cleanup:
3623 3624 3625 3626 3627
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceChangeCommit(virConnectPtr conn,
E
Eric Blake 已提交
3628
                                     unsigned int flags)
3629
{
3630
    testDriverPtr privconn = conn->privateData;
3631 3632
    int ret = -1;

E
Eric Blake 已提交
3633 3634
    virCheckFlags(0, -1);

3635 3636 3637
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3638
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3639 3640
                       _("no transaction running, "
                         "nothing to be committed."));
3641 3642 3643 3644 3645 3646 3647 3648
        goto cleanup;
    }

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

    ret = 0;

3649
 cleanup:
3650 3651 3652 3653 3654 3655
    testDriverUnlock(privconn);

    return ret;
}

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

E
Eric Blake 已提交
3661 3662
    virCheckFlags(0, -1);

3663 3664 3665
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
3666
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3667 3668
                       _("no transaction running, "
                         "nothing to rollback."));
3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681
        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;

3682
 cleanup:
3683 3684 3685
    testDriverUnlock(privconn);
    return ret;
}
3686

L
Laine Stump 已提交
3687
static char *testInterfaceGetXMLDesc(virInterfacePtr iface,
E
Eric Blake 已提交
3688
                                     unsigned int flags)
L
Laine Stump 已提交
3689
{
3690
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3691 3692 3693
    virInterfaceObjPtr privinterface;
    char *ret = NULL;

E
Eric Blake 已提交
3694 3695
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
3696 3697 3698 3699 3700 3701
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);
    testDriverUnlock(privconn);

    if (privinterface == NULL) {
3702
        virReportError(VIR_ERR_NO_INTERFACE, __FUNCTION__);
L
Laine Stump 已提交
3703 3704 3705
        goto cleanup;
    }

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

3708
 cleanup:
L
Laine Stump 已提交
3709 3710 3711 3712 3713 3714 3715
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    return ret;
}


static virInterfacePtr testInterfaceDefineXML(virConnectPtr conn, const char *xmlStr,
E
Eric Blake 已提交
3716
                                              unsigned int flags)
L
Laine Stump 已提交
3717
{
3718
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
3719 3720 3721 3722
    virInterfaceDefPtr def;
    virInterfaceObjPtr iface = NULL;
    virInterfacePtr ret = NULL;

E
Eric Blake 已提交
3723 3724
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
3725
    testDriverLock(privconn);
3726
    if ((def = virInterfaceDefParseString(xmlStr)) == NULL)
L
Laine Stump 已提交
3727 3728
        goto cleanup;

3729
    if ((iface = virInterfaceAssignDef(&privconn->ifaces, def)) == NULL)
L
Laine Stump 已提交
3730 3731 3732 3733 3734
        goto cleanup;
    def = NULL;

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

3735
 cleanup:
L
Laine Stump 已提交
3736 3737 3738 3739 3740 3741 3742 3743 3744
    virInterfaceDefFree(def);
    if (iface)
        virInterfaceObjUnlock(iface);
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceUndefine(virInterfacePtr iface)
{
3745
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3746 3747 3748 3749 3750 3751 3752 3753
    virInterfaceObjPtr privinterface;
    int ret = -1;

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

    if (privinterface == NULL) {
3754
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3755 3756 3757 3758 3759 3760 3761
        goto cleanup;
    }

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

3762
 cleanup:
L
Laine Stump 已提交
3763 3764 3765 3766 3767
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceCreate(virInterfacePtr iface,
E
Eric Blake 已提交
3768
                               unsigned int flags)
L
Laine Stump 已提交
3769
{
3770
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3771 3772 3773
    virInterfaceObjPtr privinterface;
    int ret = -1;

E
Eric Blake 已提交
3774 3775
    virCheckFlags(0, -1);

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

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

    if (privinterface->active != 0) {
3786
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
3787 3788 3789 3790 3791 3792
        goto cleanup;
    }

    privinterface->active = 1;
    ret = 0;

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

static int testInterfaceDestroy(virInterfacePtr iface,
E
Eric Blake 已提交
3801
                                unsigned int flags)
L
Laine Stump 已提交
3802
{
3803
    testDriverPtr privconn = iface->conn->privateData;
L
Laine Stump 已提交
3804 3805 3806
    virInterfaceObjPtr privinterface;
    int ret = -1;

E
Eric Blake 已提交
3807 3808
    virCheckFlags(0, -1);

L
Laine Stump 已提交
3809 3810 3811 3812 3813
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);

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

    if (privinterface->active == 0) {
3819
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
3820 3821 3822 3823 3824 3825
        goto cleanup;
    }

    privinterface->active = 0;
    ret = 0;

3826
 cleanup:
L
Laine Stump 已提交
3827 3828 3829 3830 3831 3832 3833 3834
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    testDriverUnlock(privconn);
    return ret;
}



C
Cole Robinson 已提交
3835 3836 3837 3838
/*
 * Storage Driver routines
 */

3839

3840 3841
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool)
{
C
Cole Robinson 已提交
3842 3843 3844 3845 3846

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

3847
    return VIR_STRDUP(pool->configFile, "");
C
Cole Robinson 已提交
3848 3849
}

3850

C
Cole Robinson 已提交
3851 3852
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
3853 3854
                            const unsigned char *uuid)
{
3855
    testDriverPtr privconn = conn->privateData;
3856 3857
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3858

3859
    testDriverLock(privconn);
3860
    pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid);
3861
    testDriverUnlock(privconn);
3862 3863

    if (pool == NULL) {
3864
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
3865
        goto cleanup;
C
Cole Robinson 已提交
3866 3867
    }

3868 3869
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
3870

3871
 cleanup:
3872 3873
    if (pool)
        virStoragePoolObjUnlock(pool);
3874
    return ret;
C
Cole Robinson 已提交
3875 3876 3877 3878
}

static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
3879 3880
                            const char *name)
{
3881
    testDriverPtr privconn = conn->privateData;
3882 3883
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3884

3885
    testDriverLock(privconn);
3886
    pool = virStoragePoolObjFindByName(&privconn->pools, name);
3887
    testDriverUnlock(privconn);
3888 3889

    if (pool == NULL) {
3890
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
3891
        goto cleanup;
C
Cole Robinson 已提交
3892 3893
    }

3894 3895
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
3896

3897
 cleanup:
3898 3899
    if (pool)
        virStoragePoolObjUnlock(pool);
3900
    return ret;
C
Cole Robinson 已提交
3901 3902 3903
}

static virStoragePoolPtr
3904 3905
testStoragePoolLookupByVolume(virStorageVolPtr vol)
{
C
Cole Robinson 已提交
3906 3907 3908 3909
    return testStoragePoolLookupByName(vol->conn, vol->pool);
}

static int
3910 3911
testConnectNumOfStoragePools(virConnectPtr conn)
{
3912
    testDriverPtr privconn = conn->privateData;
3913 3914
    int numActive = 0;
    size_t i;
C
Cole Robinson 已提交
3915

3916
    testDriverLock(privconn);
3917
    for (i = 0; i < privconn->pools.count; i++)
C
Cole Robinson 已提交
3918 3919
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numActive++;
3920
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3921 3922 3923 3924 3925

    return numActive;
}

static int
3926 3927
testConnectListStoragePools(virConnectPtr conn,
                            char **const names,
3928 3929
                            int nnames)
{
3930
    testDriverPtr privconn = conn->privateData;
3931 3932
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
3933

3934
    testDriverLock(privconn);
C
Cole Robinson 已提交
3935
    memset(names, 0, sizeof(*names)*nnames);
3936
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
3937
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3938
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
3939
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
3940
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
3941
            goto error;
3942 3943 3944 3945
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3946 3947 3948

    return n;

3949
 error:
3950
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
3951
        VIR_FREE(names[n]);
3952
    testDriverUnlock(privconn);
3953
    return -1;
C
Cole Robinson 已提交
3954 3955 3956
}

static int
3957 3958
testConnectNumOfDefinedStoragePools(virConnectPtr conn)
{
3959
    testDriverPtr privconn = conn->privateData;
3960 3961
    int numInactive = 0;
    size_t i;
C
Cole Robinson 已提交
3962

3963
    testDriverLock(privconn);
3964
    for (i = 0; i < privconn->pools.count; i++) {
3965
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3966 3967
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numInactive++;
3968 3969 3970
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3971 3972 3973 3974 3975

    return numInactive;
}

static int
3976 3977
testConnectListDefinedStoragePools(virConnectPtr conn,
                                   char **const names,
3978 3979
                                   int nnames)
{
3980
    testDriverPtr privconn = conn->privateData;
3981 3982
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
3983

3984
    testDriverLock(privconn);
C
Cole Robinson 已提交
3985
    memset(names, 0, sizeof(*names)*nnames);
3986
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
3987
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3988
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
3989
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
3990
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
3991
            goto error;
3992 3993 3994 3995
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3996 3997 3998

    return n;

3999
 error:
4000
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
4001
        VIR_FREE(names[n]);
4002
    testDriverUnlock(privconn);
4003
    return -1;
C
Cole Robinson 已提交
4004 4005
}

4006
static int
4007 4008 4009
testConnectListAllStoragePools(virConnectPtr conn,
                               virStoragePoolPtr **pools,
                               unsigned int flags)
4010
{
4011
    testDriverPtr privconn = conn->privateData;
4012 4013 4014 4015 4016
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

    testDriverLock(privconn);
4017 4018
    ret = virStoragePoolObjListExport(conn, privconn->pools, pools,
                                      NULL, flags);
4019 4020 4021 4022
    testDriverUnlock(privconn);

    return ret;
}
C
Cole Robinson 已提交
4023

4024 4025
static int testStoragePoolIsActive(virStoragePoolPtr pool)
{
4026
    testDriverPtr privconn = pool->conn->privateData;
4027 4028 4029 4030 4031 4032 4033
    virStoragePoolObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virStoragePoolObjFindByUUID(&privconn->pools, pool->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
4034
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4035 4036 4037 4038
        goto cleanup;
    }
    ret = virStoragePoolObjIsActive(obj);

4039
 cleanup:
4040 4041 4042 4043 4044 4045 4046
    if (obj)
        virStoragePoolObjUnlock(obj);
    return ret;
}

static int testStoragePoolIsPersistent(virStoragePoolPtr pool)
{
4047
    testDriverPtr privconn = pool->conn->privateData;
4048 4049 4050 4051 4052 4053 4054
    virStoragePoolObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virStoragePoolObjFindByUUID(&privconn->pools, pool->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
4055
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4056 4057 4058 4059
        goto cleanup;
    }
    ret = obj->configFile ? 1 : 0;

4060
 cleanup:
4061 4062 4063 4064 4065 4066 4067
    if (obj)
        virStoragePoolObjUnlock(obj);
    return ret;
}



C
Cole Robinson 已提交
4068
static int
4069 4070
testStoragePoolCreate(virStoragePoolPtr pool,
                      unsigned int flags)
E
Eric Blake 已提交
4071
{
4072
    testDriverPtr privconn = pool->conn->privateData;
4073
    virStoragePoolObjPtr privpool;
4074
    int ret = -1;
4075
    virObjectEventPtr event = NULL;
4076

E
Eric Blake 已提交
4077 4078
    virCheckFlags(0, -1);

4079
    testDriverLock(privconn);
4080 4081
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4082
    testDriverUnlock(privconn);
4083 4084

    if (privpool == NULL) {
4085
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4086
        goto cleanup;
4087 4088
    }

4089
    if (virStoragePoolObjIsActive(privpool)) {
4090 4091
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4092 4093
        goto cleanup;
    }
C
Cole Robinson 已提交
4094 4095

    privpool->active = 1;
4096 4097 4098 4099

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

4102
 cleanup:
4103
    testObjectEventQueue(privconn, event);
4104 4105
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4106
    return ret;
C
Cole Robinson 已提交
4107 4108 4109
}

static char *
4110 4111 4112 4113
testConnectFindStoragePoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type,
                                  const char *srcSpec,
                                  unsigned int flags)
C
Cole Robinson 已提交
4114
{
4115 4116 4117 4118
    virStoragePoolSourcePtr source = NULL;
    int pool_type;
    char *ret = NULL;

E
Eric Blake 已提交
4119 4120
    virCheckFlags(0, NULL);

4121 4122
    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
4123 4124
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
4125 4126 4127 4128
        goto cleanup;
    }

    if (srcSpec) {
4129
        source = virStoragePoolDefParseSourceString(srcSpec, pool_type);
4130 4131 4132 4133 4134 4135 4136
        if (!source)
            goto cleanup;
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
4137
        ignore_value(VIR_STRDUP(ret, defaultPoolSourcesLogicalXML));
4138 4139 4140
        break;

    case VIR_STORAGE_POOL_NETFS:
4141
        if (!source || !source->hosts[0].name) {
4142 4143
            virReportError(VIR_ERR_INVALID_ARG,
                           "%s", _("hostname must be specified for netfs sources"));
4144 4145 4146
            goto cleanup;
        }

4147 4148
        ignore_value(virAsprintf(&ret, defaultPoolSourcesNetFSXML,
                                 source->hosts[0].name));
4149 4150 4151
        break;

    default:
4152 4153
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source discovery"), type);
4154 4155
    }

4156
 cleanup:
4157 4158
    virStoragePoolSourceFree(source);
    return ret;
C
Cole Robinson 已提交
4159 4160 4161 4162
}


static virStoragePoolPtr
4163 4164 4165
testStoragePoolCreateXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4166
{
4167
    testDriverPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4168
    virStoragePoolDefPtr def;
4169
    virStoragePoolObjPtr pool = NULL;
4170
    virStoragePoolPtr ret = NULL;
4171
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
4172

E
Eric Blake 已提交
4173 4174
    virCheckFlags(0, NULL);

4175
    testDriverLock(privconn);
4176
    if (!(def = virStoragePoolDefParseString(xml)))
4177
        goto cleanup;
C
Cole Robinson 已提交
4178

4179 4180 4181 4182
    pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid);
    if (!pool)
        pool = virStoragePoolObjFindByName(&privconn->pools, def->name);
    if (pool) {
4183 4184
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("storage pool already exists"));
4185
        goto cleanup;
C
Cole Robinson 已提交
4186 4187
    }

4188
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4189
        goto cleanup;
4190
    def = NULL;
C
Cole Robinson 已提交
4191

4192
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4193
        virStoragePoolObjRemove(&privconn->pools, pool);
4194 4195
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4196 4197 4198
    }
    pool->active = 1;

4199 4200 4201 4202
    event = virStoragePoolEventLifecycleNew(pool->def->name, pool->def->uuid,
                                            VIR_STORAGE_POOL_EVENT_STARTED,
                                            0);

4203 4204
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4205

4206
 cleanup:
4207
    virStoragePoolDefFree(def);
4208
    testObjectEventQueue(privconn, event);
4209 4210 4211
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4212
    return ret;
C
Cole Robinson 已提交
4213 4214 4215
}

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

E
Eric Blake 已提交
4226 4227
    virCheckFlags(0, NULL);

4228
    testDriverLock(privconn);
4229
    if (!(def = virStoragePoolDefParseString(xml)))
4230
        goto cleanup;
C
Cole Robinson 已提交
4231 4232 4233 4234 4235

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

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

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

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

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

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

static int
4263 4264
testStoragePoolUndefine(virStoragePoolPtr pool)
{
4265
    testDriverPtr privconn = pool->conn->privateData;
4266
    virStoragePoolObjPtr privpool;
4267
    int ret = -1;
4268
    virObjectEventPtr event = NULL;
4269

4270
    testDriverLock(privconn);
4271 4272 4273 4274
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
4275
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4276
        goto cleanup;
4277 4278
    }

4279
    if (virStoragePoolObjIsActive(privpool)) {
4280 4281
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4282 4283
        goto cleanup;
    }
C
Cole Robinson 已提交
4284

4285 4286 4287 4288
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_UNDEFINED,
                                            0);

C
Cole Robinson 已提交
4289
    virStoragePoolObjRemove(&privconn->pools, privpool);
4290
    privpool = NULL;
4291
    ret = 0;
C
Cole Robinson 已提交
4292

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

static int
4302
testStoragePoolBuild(virStoragePoolPtr pool,
E
Eric Blake 已提交
4303 4304
                     unsigned int flags)
{
4305
    testDriverPtr privconn = pool->conn->privateData;
4306
    virStoragePoolObjPtr privpool;
4307
    int ret = -1;
4308

E
Eric Blake 已提交
4309 4310
    virCheckFlags(0, -1);

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

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

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

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


static int
4336 4337
testStoragePoolDestroy(virStoragePoolPtr pool)
{
4338
    testDriverPtr privconn = pool->conn->privateData;
4339
    virStoragePoolObjPtr privpool;
4340
    int ret = -1;
4341
    virObjectEventPtr event = NULL;
4342

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

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

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

    privpool->active = 0;
4359 4360 4361
    event = virStoragePoolEventLifecycleNew(privpool->def->name, privpool->def->uuid,
                                            VIR_STORAGE_POOL_EVENT_STOPPED,
                                            0);
C
Cole Robinson 已提交
4362

4363
    if (privpool->configFile == NULL) {
C
Cole Robinson 已提交
4364
        virStoragePoolObjRemove(&privconn->pools, privpool);
4365 4366
        privpool = NULL;
    }
4367
    ret = 0;
C
Cole Robinson 已提交
4368

4369
 cleanup:
4370
    testObjectEventQueue(privconn, event);
4371 4372 4373
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
4374
    return ret;
C
Cole Robinson 已提交
4375 4376 4377 4378
}


static int
4379
testStoragePoolDelete(virStoragePoolPtr pool,
E
Eric Blake 已提交
4380 4381
                      unsigned int flags)
{
4382
    testDriverPtr privconn = pool->conn->privateData;
4383
    virStoragePoolObjPtr privpool;
4384
    int ret = -1;
4385

E
Eric Blake 已提交
4386 4387
    virCheckFlags(0, -1);

4388
    testDriverLock(privconn);
4389 4390
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4391
    testDriverUnlock(privconn);
4392 4393

    if (privpool == NULL) {
4394
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4395 4396 4397 4398
        goto cleanup;
    }

    if (virStoragePoolObjIsActive(privpool)) {
4399 4400
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4401
        goto cleanup;
4402 4403
    }

4404
    ret = 0;
C
Cole Robinson 已提交
4405

4406
 cleanup:
4407 4408
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4409
    return ret;
C
Cole Robinson 已提交
4410 4411 4412 4413
}


static int
4414
testStoragePoolRefresh(virStoragePoolPtr pool,
E
Eric Blake 已提交
4415 4416
                       unsigned int flags)
{
4417
    testDriverPtr privconn = pool->conn->privateData;
4418
    virStoragePoolObjPtr privpool;
4419
    int ret = -1;
4420
    virObjectEventPtr event = NULL;
4421

E
Eric Blake 已提交
4422 4423
    virCheckFlags(0, -1);

4424
    testDriverLock(privconn);
4425 4426
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4427
    testDriverUnlock(privconn);
4428 4429

    if (privpool == NULL) {
4430
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4431
        goto cleanup;
4432 4433 4434
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4435 4436
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4437
        goto cleanup;
4438
    }
4439

4440
    event = virStoragePoolEventRefreshNew(pool->name, pool->uuid);
4441
    ret = 0;
C
Cole Robinson 已提交
4442

4443
 cleanup:
4444
    testObjectEventQueue(privconn, event);
4445 4446
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4447
    return ret;
C
Cole Robinson 已提交
4448 4449 4450 4451
}


static int
4452
testStoragePoolGetInfo(virStoragePoolPtr pool,
4453 4454
                       virStoragePoolInfoPtr info)
{
4455
    testDriverPtr privconn = pool->conn->privateData;
4456
    virStoragePoolObjPtr privpool;
4457
    int ret = -1;
4458

4459
    testDriverLock(privconn);
4460 4461
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4462
    testDriverUnlock(privconn);
4463 4464

    if (privpool == NULL) {
4465
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4466
        goto cleanup;
4467
    }
C
Cole Robinson 已提交
4468 4469 4470 4471 4472 4473 4474 4475 4476

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

4479
 cleanup:
4480 4481
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4482
    return ret;
C
Cole Robinson 已提交
4483 4484 4485
}

static char *
4486
testStoragePoolGetXMLDesc(virStoragePoolPtr pool,
E
Eric Blake 已提交
4487 4488
                          unsigned int flags)
{
4489
    testDriverPtr privconn = pool->conn->privateData;
4490
    virStoragePoolObjPtr privpool;
4491
    char *ret = NULL;
4492

E
Eric Blake 已提交
4493 4494
    virCheckFlags(0, NULL);

4495
    testDriverLock(privconn);
4496 4497
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4498
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4499

4500
    if (privpool == NULL) {
4501
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4502
        goto cleanup;
4503 4504
    }

4505
    ret = virStoragePoolDefFormat(privpool->def);
4506

4507
 cleanup:
4508 4509
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4510
    return ret;
C
Cole Robinson 已提交
4511 4512 4513
}

static int
4514
testStoragePoolGetAutostart(virStoragePoolPtr pool,
4515 4516
                            int *autostart)
{
4517
    testDriverPtr privconn = pool->conn->privateData;
4518
    virStoragePoolObjPtr privpool;
4519
    int ret = -1;
4520

4521
    testDriverLock(privconn);
4522 4523
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4524
    testDriverUnlock(privconn);
4525 4526

    if (privpool == NULL) {
4527
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4528
        goto cleanup;
4529
    }
C
Cole Robinson 已提交
4530 4531 4532 4533 4534 4535

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

4538
 cleanup:
4539 4540
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4541
    return ret;
C
Cole Robinson 已提交
4542 4543 4544
}

static int
4545
testStoragePoolSetAutostart(virStoragePoolPtr pool,
4546 4547
                            int autostart)
{
4548
    testDriverPtr privconn = pool->conn->privateData;
4549
    virStoragePoolObjPtr privpool;
4550
    int ret = -1;
4551

4552
    testDriverLock(privconn);
4553 4554
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4555
    testDriverUnlock(privconn);
4556 4557

    if (privpool == NULL) {
4558
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4559
        goto cleanup;
4560
    }
C
Cole Robinson 已提交
4561 4562

    if (!privpool->configFile) {
4563 4564
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("pool has no config file"));
4565
        goto cleanup;
C
Cole Robinson 已提交
4566 4567 4568 4569
    }

    autostart = (autostart != 0);
    privpool->autostart = autostart;
4570 4571
    ret = 0;

4572
 cleanup:
4573 4574
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4575
    return ret;
C
Cole Robinson 已提交
4576 4577 4578 4579
}


static int
4580 4581
testStoragePoolNumOfVolumes(virStoragePoolPtr pool)
{
4582
    testDriverPtr privconn = pool->conn->privateData;
4583
    virStoragePoolObjPtr privpool;
4584
    int ret = -1;
4585

4586
    testDriverLock(privconn);
4587 4588
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4589
    testDriverUnlock(privconn);
4590 4591

    if (privpool == NULL) {
4592
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4593
        goto cleanup;
4594 4595 4596
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4597 4598
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4599
        goto cleanup;
4600
    }
C
Cole Robinson 已提交
4601

4602 4603
    ret = privpool->volumes.count;

4604
 cleanup:
4605 4606
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4607
    return ret;
C
Cole Robinson 已提交
4608 4609 4610
}

static int
4611
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4612
                           char **const names,
4613 4614
                           int maxnames)
{
4615
    testDriverPtr privconn = pool->conn->privateData;
4616
    virStoragePoolObjPtr privpool;
4617 4618
    size_t i = 0;
    int n = 0;
C
Cole Robinson 已提交
4619

4620
    memset(names, 0, maxnames * sizeof(*names));
4621 4622

    testDriverLock(privconn);
4623 4624
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4625
    testDriverUnlock(privconn);
4626 4627

    if (privpool == NULL) {
4628
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4629
        goto cleanup;
4630 4631 4632 4633
    }


    if (!virStoragePoolObjIsActive(privpool)) {
4634 4635
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4636
        goto cleanup;
4637 4638
    }

4639
    for (i = 0; i < privpool->volumes.count && n < maxnames; i++) {
4640
        if (VIR_STRDUP(names[n++], privpool->volumes.objs[i]->name) < 0)
C
Cole Robinson 已提交
4641 4642 4643
            goto cleanup;
    }

4644
    virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4645 4646 4647
    return n;

 cleanup:
4648
    for (n = 0; n < maxnames; n++)
C
Cole Robinson 已提交
4649 4650
        VIR_FREE(names[i]);

4651
    memset(names, 0, maxnames * sizeof(*names));
4652 4653
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4654 4655 4656
    return -1;
}

4657 4658 4659
static int
testStoragePoolListAllVolumes(virStoragePoolPtr obj,
                              virStorageVolPtr **vols,
4660 4661
                              unsigned int flags)
{
4662
    testDriverPtr privconn = obj->conn->privateData;
4663
    virStoragePoolObjPtr pool;
4664
    size_t i;
4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693
    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;
    }

4694
    if (VIR_ALLOC_N(tmp_vols, pool->volumes.count + 1) < 0)
4695 4696
         goto cleanup;

4697
    for (i = 0; i < pool->volumes.count; i++) {
4698 4699
        if (!(vol = virGetStorageVol(obj->conn, pool->def->name,
                                     pool->volumes.objs[i]->name,
4700 4701
                                     pool->volumes.objs[i]->key,
                                     NULL, NULL)))
4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715
            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]);
        }
4716
        VIR_FREE(tmp_vols);
4717 4718 4719 4720 4721 4722 4723
    }

    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
C
Cole Robinson 已提交
4724 4725

static virStorageVolPtr
4726
testStorageVolLookupByName(virStoragePoolPtr pool,
4727 4728
                           const char *name ATTRIBUTE_UNUSED)
{
4729
    testDriverPtr privconn = pool->conn->privateData;
4730 4731
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
4732
    virStorageVolPtr ret = NULL;
4733

4734
    testDriverLock(privconn);
4735 4736
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4737
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4738

4739
    if (privpool == NULL) {
4740
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4741
        goto cleanup;
4742 4743 4744 4745
    }


    if (!virStoragePoolObjIsActive(privpool)) {
4746 4747
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4748
        goto cleanup;
4749 4750 4751 4752 4753
    }

    privvol = virStorageVolDefFindByName(privpool, name);

    if (!privvol) {
4754 4755
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"), name);
4756
        goto cleanup;
C
Cole Robinson 已提交
4757 4758
    }

4759
    ret = virGetStorageVol(pool->conn, privpool->def->name,
4760 4761
                           privvol->name, privvol->key,
                           NULL, NULL);
4762

4763
 cleanup:
4764 4765
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4766
    return ret;
C
Cole Robinson 已提交
4767 4768 4769 4770
}


static virStorageVolPtr
4771
testStorageVolLookupByKey(virConnectPtr conn,
4772 4773
                          const char *key)
{
4774
    testDriverPtr privconn = conn->privateData;
4775
    size_t i;
4776
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4777

4778
    testDriverLock(privconn);
4779
    for (i = 0; i < privconn->pools.count; i++) {
4780
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4781
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4782
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4783 4784
                virStorageVolDefFindByKey(privconn->pools.objs[i], key);

4785 4786 4787 4788
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
4789 4790
                                       privvol->key,
                                       NULL, NULL);
4791
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
4792 4793
                break;
            }
C
Cole Robinson 已提交
4794
        }
4795
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4796
    }
4797
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4798

4799
    if (!ret)
4800 4801
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching key '%s'"), key);
4802 4803

    return ret;
C
Cole Robinson 已提交
4804 4805 4806
}

static virStorageVolPtr
4807
testStorageVolLookupByPath(virConnectPtr conn,
4808 4809
                           const char *path)
{
4810
    testDriverPtr privconn = conn->privateData;
4811
    size_t i;
4812
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4813

4814
    testDriverLock(privconn);
4815
    for (i = 0; i < privconn->pools.count; i++) {
4816
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4817
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4818
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4819 4820
                virStorageVolDefFindByPath(privconn->pools.objs[i], path);

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

4835
    if (!ret)
4836 4837
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching path '%s'"), path);
4838 4839

    return ret;
C
Cole Robinson 已提交
4840 4841 4842
}

static virStorageVolPtr
4843 4844 4845
testStorageVolCreateXML(virStoragePoolPtr pool,
                        const char *xmldesc,
                        unsigned int flags)
E
Eric Blake 已提交
4846
{
4847
    testDriverPtr privconn = pool->conn->privateData;
4848
    virStoragePoolObjPtr privpool;
4849 4850
    virStorageVolDefPtr privvol = NULL;
    virStorageVolPtr ret = NULL;
4851

E
Eric Blake 已提交
4852 4853
    virCheckFlags(0, NULL);

4854
    testDriverLock(privconn);
4855 4856
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4857
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4858

4859
    if (privpool == NULL) {
4860
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4861
        goto cleanup;
4862 4863 4864
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4865 4866
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4867
        goto cleanup;
4868
    }
C
Cole Robinson 已提交
4869

4870
    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
4871
    if (privvol == NULL)
4872
        goto cleanup;
4873 4874

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
4875 4876
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
4877
        goto cleanup;
C
Cole Robinson 已提交
4878 4879 4880
    }

    /* Make sure enough space */
4881
    if ((privpool->def->allocation + privvol->target.allocation) >
C
Cole Robinson 已提交
4882
         privpool->def->capacity) {
4883 4884 4885
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
4886
        goto cleanup;
C
Cole Robinson 已提交
4887 4888
    }

4889 4890
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
4891
                    privvol->name) == -1)
4892
        goto cleanup;
C
Cole Robinson 已提交
4893

4894 4895 4896
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
        VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
                                privpool->volumes.count, privvol) < 0)
4897
        goto cleanup;
C
Cole Robinson 已提交
4898

4899
    privpool->def->allocation += privvol->target.allocation;
C
Cole Robinson 已提交
4900 4901 4902
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

4903
    ret = virGetStorageVol(pool->conn, privpool->def->name,
4904 4905
                           privvol->name, privvol->key,
                           NULL, NULL);
4906
    privvol = NULL;
4907

4908
 cleanup:
4909
    virStorageVolDefFree(privvol);
4910 4911
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4912
    return ret;
C
Cole Robinson 已提交
4913 4914
}

4915
static virStorageVolPtr
4916 4917 4918 4919
testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
                            const char *xmldesc,
                            virStorageVolPtr clonevol,
                            unsigned int flags)
E
Eric Blake 已提交
4920
{
4921
    testDriverPtr privconn = pool->conn->privateData;
4922 4923 4924 4925
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol = NULL, origvol = NULL;
    virStorageVolPtr ret = NULL;

E
Eric Blake 已提交
4926 4927
    virCheckFlags(0, NULL);

4928 4929 4930 4931 4932 4933
    testDriverLock(privconn);
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
    testDriverUnlock(privconn);

    if (privpool == NULL) {
4934
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4935 4936 4937 4938
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4939 4940
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4941 4942 4943
        goto cleanup;
    }

4944
    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
4945 4946 4947 4948
    if (privvol == NULL)
        goto cleanup;

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
4949 4950
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
4951 4952 4953 4954 4955
        goto cleanup;
    }

    origvol = virStorageVolDefFindByName(privpool, clonevol->name);
    if (!origvol) {
4956 4957 4958
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       clonevol->name);
4959 4960 4961 4962
        goto cleanup;
    }

    /* Make sure enough space */
4963
    if ((privpool->def->allocation + privvol->target.allocation) >
4964
         privpool->def->capacity) {
4965 4966 4967
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
4968 4969 4970 4971 4972
        goto cleanup;
    }
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

4973 4974
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
4975
                    privvol->name) == -1)
4976 4977
        goto cleanup;

4978 4979 4980
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
        VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
                                privpool->volumes.count, privvol) < 0)
4981 4982
        goto cleanup;

4983
    privpool->def->allocation += privvol->target.allocation;
4984 4985 4986 4987
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    ret = virGetStorageVol(pool->conn, privpool->def->name,
4988 4989
                           privvol->name, privvol->key,
                           NULL, NULL);
4990 4991
    privvol = NULL;

4992
 cleanup:
4993 4994 4995 4996 4997 4998
    virStorageVolDefFree(privvol);
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    return ret;
}

C
Cole Robinson 已提交
4999
static int
5000 5001
testStorageVolDelete(virStorageVolPtr vol,
                     unsigned int flags)
E
Eric Blake 已提交
5002
{
5003
    testDriverPtr privconn = vol->conn->privateData;
5004 5005
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5006
    size_t i;
5007
    int ret = -1;
C
Cole Robinson 已提交
5008

E
Eric Blake 已提交
5009 5010
    virCheckFlags(0, -1);

5011
    testDriverLock(privconn);
5012 5013
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5014
    testDriverUnlock(privconn);
5015 5016

    if (privpool == NULL) {
5017
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5018
        goto cleanup;
5019 5020 5021 5022 5023 5024
    }


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

    if (privvol == NULL) {
5025 5026 5027
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5028
        goto cleanup;
5029 5030 5031
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5032 5033
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5034
        goto cleanup;
5035 5036 5037
    }


5038
    privpool->def->allocation -= privvol->target.allocation;
C
Cole Robinson 已提交
5039 5040 5041
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

5042
    for (i = 0; i < privpool->volumes.count; i++) {
C
Cole Robinson 已提交
5043 5044 5045
        if (privpool->volumes.objs[i] == privvol) {
            virStorageVolDefFree(privvol);

5046
            VIR_DELETE_ELEMENT(privpool->volumes.objs, i, privpool->volumes.count);
C
Cole Robinson 已提交
5047 5048 5049
            break;
        }
    }
5050
    ret = 0;
C
Cole Robinson 已提交
5051

5052
 cleanup:
5053 5054
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5055
    return ret;
C
Cole Robinson 已提交
5056 5057 5058
}


5059 5060
static int testStorageVolumeTypeForPool(int pooltype)
{
C
Cole Robinson 已提交
5061

5062
    switch (pooltype) {
C
Cole Robinson 已提交
5063 5064 5065 5066 5067 5068 5069 5070 5071 5072
        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
5073
testStorageVolGetInfo(virStorageVolPtr vol,
5074 5075
                      virStorageVolInfoPtr info)
{
5076
    testDriverPtr privconn = vol->conn->privateData;
5077 5078
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5079
    int ret = -1;
5080

5081
    testDriverLock(privconn);
5082 5083
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5084
    testDriverUnlock(privconn);
5085 5086

    if (privpool == NULL) {
5087
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5088
        goto cleanup;
5089 5090 5091 5092 5093
    }

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

    if (privvol == NULL) {
5094 5095 5096
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5097
        goto cleanup;
5098 5099 5100
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5101 5102
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5103
        goto cleanup;
5104
    }
C
Cole Robinson 已提交
5105 5106 5107

    memset(info, 0, sizeof(*info));
    info->type = testStorageVolumeTypeForPool(privpool->def->type);
5108 5109
    info->capacity = privvol->target.capacity;
    info->allocation = privvol->target.allocation;
5110
    ret = 0;
C
Cole Robinson 已提交
5111

5112
 cleanup:
5113 5114
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5115
    return ret;
C
Cole Robinson 已提交
5116 5117 5118
}

static char *
5119 5120
testStorageVolGetXMLDesc(virStorageVolPtr vol,
                         unsigned int flags)
E
Eric Blake 已提交
5121
{
5122
    testDriverPtr privconn = vol->conn->privateData;
5123 5124
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5125
    char *ret = NULL;
5126

E
Eric Blake 已提交
5127 5128
    virCheckFlags(0, NULL);

5129
    testDriverLock(privconn);
5130 5131
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5132
    testDriverUnlock(privconn);
5133 5134

    if (privpool == NULL) {
5135
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5136
        goto cleanup;
5137 5138 5139 5140 5141
    }

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

    if (privvol == NULL) {
5142 5143 5144
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5145
        goto cleanup;
5146
    }
C
Cole Robinson 已提交
5147

5148
    if (!virStoragePoolObjIsActive(privpool)) {
5149 5150
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5151
        goto cleanup;
5152 5153
    }

5154
    ret = virStorageVolDefFormat(privpool->def, privvol);
5155

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

static char *
5163 5164
testStorageVolGetPath(virStorageVolPtr vol)
{
5165
    testDriverPtr privconn = vol->conn->privateData;
5166 5167
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5168
    char *ret = NULL;
5169

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 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
    ignore_value(VIR_STRDUP(ret, privvol->target.path));
5196

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

5203

5204
/* Node device implementations */
5205

5206 5207 5208
static int
testNodeNumOfDevices(virConnectPtr conn,
                     const char *cap,
E
Eric Blake 已提交
5209
                     unsigned int flags)
5210
{
5211
    testDriverPtr driver = conn->privateData;
5212
    int ndevs = 0;
5213
    size_t i;
5214

E
Eric Blake 已提交
5215 5216
    virCheckFlags(0, -1);

5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231
    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 已提交
5232
                    unsigned int flags)
5233
{
5234
    testDriverPtr driver = conn->privateData;
5235
    int ndevs = 0;
5236
    size_t i;
5237

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

5240 5241 5242 5243 5244
    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)) {
5245
            if (VIR_STRDUP(names[ndevs++], driver->devs.objs[i]->def->name) < 0) {
5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266
                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)
{
5267
    testDriverPtr driver = conn->privateData;
5268 5269 5270 5271 5272 5273 5274 5275
    virNodeDeviceObjPtr obj;
    virNodeDevicePtr ret = NULL;

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

    if (!obj) {
5276 5277 5278
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       name);
5279 5280 5281 5282 5283
        goto cleanup;
    }

    ret = virGetNodeDevice(conn, name);

5284
 cleanup:
5285 5286 5287 5288 5289 5290
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

static char *
5291
testNodeDeviceGetXMLDesc(virNodeDevicePtr dev,
E
Eric Blake 已提交
5292
                         unsigned int flags)
5293
{
5294
    testDriverPtr driver = dev->conn->privateData;
5295 5296 5297
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

E
Eric Blake 已提交
5298 5299
    virCheckFlags(0, NULL);

5300 5301 5302 5303 5304
    testDriverLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
    testDriverUnlock(driver);

    if (!obj) {
5305 5306 5307
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5308 5309 5310
        goto cleanup;
    }

5311
    ret = virNodeDeviceDefFormat(obj->def);
5312

5313
 cleanup:
5314 5315 5316 5317 5318 5319 5320 5321
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

static char *
testNodeDeviceGetParent(virNodeDevicePtr dev)
{
5322
    testDriverPtr driver = dev->conn->privateData;
5323 5324 5325 5326 5327 5328 5329 5330
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

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

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

    if (obj->def->parent) {
5338
        ignore_value(VIR_STRDUP(ret, obj->def->parent));
5339
    } else {
5340 5341
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no parent for this device"));
5342 5343
    }

5344
 cleanup:
5345 5346 5347 5348 5349
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

5350

5351 5352 5353
static int
testNodeDeviceNumOfCaps(virNodeDevicePtr dev)
{
5354
    testDriverPtr driver = dev->conn->privateData;
5355 5356 5357 5358 5359 5360 5361 5362 5363 5364
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

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

    if (!obj) {
5365 5366 5367
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5368 5369 5370 5371 5372 5373 5374
        goto cleanup;
    }

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

5375
 cleanup:
5376 5377 5378 5379 5380 5381 5382 5383 5384
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}


static int
testNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
5385
    testDriverPtr driver = dev->conn->privateData;
5386 5387 5388 5389 5390 5391 5392 5393 5394 5395
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

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

    if (!obj) {
5396 5397 5398
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5399 5400 5401 5402
        goto cleanup;
    }

    for (caps = obj->def->caps; caps && ncaps < maxnames; caps = caps->next) {
5403
        if (VIR_STRDUP(names[ncaps++], virNodeDevCapTypeToString(caps->data.type)) < 0)
5404 5405 5406 5407
            goto cleanup;
    }
    ret = ncaps;

5408
 cleanup:
5409 5410 5411 5412 5413 5414 5415 5416 5417 5418
    if (obj)
        virNodeDeviceObjUnlock(obj);
    if (ret == -1) {
        --ncaps;
        while (--ncaps >= 0)
            VIR_FREE(names[ncaps]);
    }
    return ret;
}

5419 5420 5421
static virNodeDevicePtr
testNodeDeviceCreateXML(virConnectPtr conn,
                        const char *xmlDesc,
E
Eric Blake 已提交
5422
                        unsigned int flags)
5423
{
5424
    testDriverPtr driver = conn->privateData;
5425 5426 5427 5428 5429 5430
    virNodeDeviceDefPtr def = NULL;
    virNodeDeviceObjPtr obj = NULL;
    char *wwnn = NULL, *wwpn = NULL;
    int parent_host = -1;
    virNodeDevicePtr dev = NULL;
    virNodeDevCapsDefPtr caps;
5431
    virObjectEventPtr event = NULL;
5432

E
Eric Blake 已提交
5433 5434
    virCheckFlags(0, NULL);

5435 5436
    testDriverLock(driver);

5437
    def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, NULL);
5438
    if (def == NULL)
5439 5440 5441
        goto cleanup;

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

5445
    if (virNodeDeviceGetParentHost(&driver->devs,
5446 5447 5448 5449 5450 5451 5452 5453 5454
                                   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);
5455
    if (VIR_STRDUP(def->name, wwpn) < 0)
5456 5457
        goto cleanup;

J
John Ferlan 已提交
5458 5459
    /* Fill in a random 'host' and 'unique_id' value,
     * since this would also come from the backend */
5460 5461
    caps = def->caps;
    while (caps) {
5462
        if (caps->data.type != VIR_NODE_DEV_CAP_SCSI_HOST)
5463 5464
            continue;

5465
        caps->data.scsi_host.host = virRandomBits(10);
J
John Ferlan 已提交
5466
        caps->data.scsi_host.unique_id = 2;
5467 5468 5469 5470
        caps = caps->next;
    }


5471
    if (!(obj = virNodeDeviceAssignDef(&driver->devs, def)))
5472 5473 5474
        goto cleanup;
    virNodeDeviceObjUnlock(obj);

5475 5476 5477 5478
    event = virNodeDeviceEventLifecycleNew(def->name,
                                           VIR_NODE_DEVICE_EVENT_CREATED,
                                           0);

5479 5480
    dev = virGetNodeDevice(conn, def->name);
    def = NULL;
5481
 cleanup:
5482
    testDriverUnlock(driver);
5483
    virNodeDeviceDefFree(def);
5484
    testObjectEventQueue(driver, event);
5485 5486 5487 5488 5489 5490 5491 5492 5493
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return dev;
}

static int
testNodeDeviceDestroy(virNodeDevicePtr dev)
{
    int ret = 0;
5494
    testDriverPtr driver = dev->conn->privateData;
5495 5496 5497
    virNodeDeviceObjPtr obj = NULL;
    char *parent_name = NULL, *wwnn = NULL, *wwpn = NULL;
    int parent_host = -1;
5498
    virObjectEventPtr event = NULL;
5499 5500 5501 5502 5503 5504

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

    if (!obj) {
5505 5506 5507
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5508 5509 5510
        goto out;
    }

5511
    if (virNodeDeviceGetWWNs(obj->def, &wwnn, &wwpn) == -1)
5512 5513
        goto out;

5514
    if (VIR_STRDUP(parent_name, obj->def->parent) < 0)
5515 5516 5517 5518 5519 5520 5521 5522 5523
        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 */
5524
    if (virNodeDeviceGetParentHost(&driver->devs,
5525 5526 5527 5528 5529 5530 5531
                                   dev->name,
                                   parent_name,
                                   &parent_host) == -1) {
        obj = NULL;
        goto out;
    }

5532 5533 5534 5535
    event = virNodeDeviceEventLifecycleNew(dev->name,
                                           VIR_NODE_DEVICE_EVENT_DELETED,
                                           0);

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

5539
 out:
5540 5541
    if (obj)
        virNodeDeviceObjUnlock(obj);
5542
    testObjectEventQueue(driver, event);
5543 5544 5545 5546 5547 5548
    VIR_FREE(parent_name);
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return ret;
}

5549 5550

/* Domain event implementations */
5551
static int
5552 5553 5554 5555
testConnectDomainEventRegister(virConnectPtr conn,
                               virConnectDomainEventCallback callback,
                               void *opaque,
                               virFreeCallback freecb)
5556
{
5557
    testDriverPtr driver = conn->privateData;
5558
    int ret = 0;
5559

5560
    if (virDomainEventStateRegister(conn, driver->eventState,
5561 5562
                                    callback, opaque, freecb) < 0)
        ret = -1;
5563 5564 5565 5566

    return ret;
}

5567

5568
static int
5569 5570
testConnectDomainEventDeregister(virConnectPtr conn,
                                 virConnectDomainEventCallback callback)
5571
{
5572
    testDriverPtr driver = conn->privateData;
5573
    int ret = 0;
5574

5575
    if (virDomainEventStateDeregister(conn, driver->eventState,
5576 5577
                                      callback) < 0)
        ret = -1;
5578 5579 5580 5581

    return ret;
}

5582 5583

static int
5584 5585 5586 5587 5588 5589
testConnectDomainEventRegisterAny(virConnectPtr conn,
                                  virDomainPtr dom,
                                  int eventID,
                                  virConnectDomainEventGenericCallback callback,
                                  void *opaque,
                                  virFreeCallback freecb)
5590
{
5591
    testDriverPtr driver = conn->privateData;
5592 5593
    int ret;

5594
    if (virDomainEventStateRegisterID(conn, driver->eventState,
5595 5596
                                      dom, eventID,
                                      callback, opaque, freecb, &ret) < 0)
5597
        ret = -1;
5598 5599 5600 5601 5602

    return ret;
}

static int
5603 5604
testConnectDomainEventDeregisterAny(virConnectPtr conn,
                                    int callbackID)
5605
{
5606
    testDriverPtr driver = conn->privateData;
5607
    int ret = 0;
5608

5609
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
5610 5611
                                        callbackID) < 0)
        ret = -1;
5612 5613 5614 5615 5616

    return ret;
}


5617 5618 5619 5620 5621 5622 5623 5624
static int
testConnectNetworkEventRegisterAny(virConnectPtr conn,
                                   virNetworkPtr net,
                                   int eventID,
                                   virConnectNetworkEventGenericCallback callback,
                                   void *opaque,
                                   virFreeCallback freecb)
{
5625
    testDriverPtr driver = conn->privateData;
5626 5627
    int ret;

5628
    if (virNetworkEventStateRegisterID(conn, driver->eventState,
5629
                                       net, eventID, callback,
5630 5631 5632 5633 5634 5635 5636 5637 5638 5639
                                       opaque, freecb, &ret) < 0)
        ret = -1;

    return ret;
}

static int
testConnectNetworkEventDeregisterAny(virConnectPtr conn,
                                     int callbackID)
{
5640
    testDriverPtr driver = conn->privateData;
5641
    int ret = 0;
5642

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

    return ret;
}

5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682
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;
}

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 5712 5713 5714 5715
static int
testConnectNodeDeviceEventRegisterAny(virConnectPtr conn,
                                      virNodeDevicePtr dev,
                                      int eventID,
                                      virConnectNodeDeviceEventGenericCallback callback,
                                      void *opaque,
                                      virFreeCallback freecb)
{
    testDriverPtr driver = conn->privateData;
    int ret;

    if (virNodeDeviceEventStateRegisterID(conn, driver->eventState,
                                          dev, eventID, callback,
                                          opaque, freecb, &ret) < 0)
        ret = -1;

    return ret;
}

static int
testConnectNodeDeviceEventDeregisterAny(virConnectPtr conn,
                                        int callbackID)
{
    testDriverPtr driver = conn->privateData;
    int ret = 0;

    if (virObjectEventStateDeregisterID(conn, driver->eventState,
                                        callbackID) < 0)
        ret = -1;

    return ret;
}

5716 5717 5718
static int testConnectListAllDomains(virConnectPtr conn,
                                     virDomainPtr **domains,
                                     unsigned int flags)
5719
{
5720
    testDriverPtr privconn = conn->privateData;
5721

O
Osier Yang 已提交
5722
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
5723

5724 5725
    return virDomainObjListExport(privconn->domains, conn, domains,
                                  NULL, flags);
5726 5727
}

5728
static int
P
Peter Krempa 已提交
5729
testNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,
5730 5731 5732 5733 5734 5735 5736
                  unsigned char **cpumap,
                  unsigned int *online,
                  unsigned int flags)
{
    virCheckFlags(0, -1);

    if (cpumap) {
5737
        if (VIR_ALLOC_N(*cpumap, 1) < 0)
P
Peter Krempa 已提交
5738
            return -1;
5739 5740 5741 5742 5743 5744
        *cpumap[0] = 0x15;
    }

    if (online)
        *online = 3;

P
Peter Krempa 已提交
5745
    return  8;
5746 5747
}

5748 5749 5750 5751 5752 5753 5754 5755 5756 5757
static char *
testDomainScreenshot(virDomainPtr dom ATTRIBUTE_UNUSED,
                     virStreamPtr st,
                     unsigned int screen ATTRIBUTE_UNUSED,
                     unsigned int flags)
{
    char *ret = NULL;

    virCheckFlags(0, NULL);

5758
    if (VIR_STRDUP(ret, "image/png") < 0)
5759 5760
        return NULL;

5761
    if (virFDStreamOpenFile(st, PKGDATADIR "/libvirtLogo.png", 0, 0, O_RDONLY) < 0)
5762 5763 5764 5765 5766
        VIR_FREE(ret);

    return ret;
}

5767 5768 5769 5770 5771 5772 5773 5774 5775
static int
testConnectGetCPUModelNames(virConnectPtr conn ATTRIBUTE_UNUSED,
                            const char *arch,
                            char ***models,
                            unsigned int flags)
{
    virCheckFlags(0, -1);
    return cpuGetModels(arch, models);
}
5776

C
Cole Robinson 已提交
5777 5778 5779
static int
testDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
5780
    testDriverPtr privconn = dom->conn->privateData;
C
Cole Robinson 已提交
5781
    virDomainObjPtr vm = NULL;
5782
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
5783 5784 5785 5786 5787 5788
    int ret = -1;

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

5789 5790
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804

    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);
5805
    event = virDomainEventLifecycleNewFromObj(vm,
C
Cole Robinson 已提交
5806 5807 5808 5809 5810
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
    vm->hasManagedSave = true;

    ret = 0;
5811
 cleanup:
5812
    virDomainObjEndAPI(&vm);
5813
    testObjectEventQueue(privconn, event);
C
Cole Robinson 已提交
5814 5815 5816 5817 5818 5819 5820 5821 5822

    return ret;
}


static int
testDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm;
5823
    int ret;
C
Cole Robinson 已提交
5824 5825 5826

    virCheckFlags(0, -1);

5827 5828
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5829 5830

    ret = vm->hasManagedSave;
5831

5832
    virDomainObjEndAPI(&vm);
C
Cole Robinson 已提交
5833 5834 5835 5836 5837 5838 5839 5840 5841 5842
    return ret;
}

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

    virCheckFlags(0, -1);

5843 5844
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
5845 5846

    vm->hasManagedSave = false;
5847

5848
    virDomainObjEndAPI(&vm);
5849
    return 0;
C
Cole Robinson 已提交
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 5883 5884 5885 5886
/*
 * 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;
5887
    int n;
5888 5889 5890 5891 5892

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5893
        return -1;
5894 5895 5896

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

5897
    virDomainObjEndAPI(&vm);
5898 5899 5900 5901 5902 5903 5904 5905 5906 5907
    return n;
}

static int
testDomainSnapshotListNames(virDomainPtr domain,
                            char **names,
                            int nameslen,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
5908
    int n;
5909 5910 5911 5912 5913

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5914
        return -1;
5915 5916 5917 5918

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

5919
    virDomainObjEndAPI(&vm);
5920 5921 5922 5923 5924 5925 5926 5927 5928
    return n;
}

static int
testDomainListAllSnapshots(virDomainPtr domain,
                           virDomainSnapshotPtr **snaps,
                           unsigned int flags)
{
    virDomainObjPtr vm = NULL;
5929
    int n;
5930 5931 5932 5933 5934

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
5935
        return -1;
5936 5937 5938

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

5939
    virDomainObjEndAPI(&vm);
5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956
    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)))
5957
        return -1;
5958 5959 5960 5961 5962 5963 5964

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

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

5965
 cleanup:
5966
    virDomainObjEndAPI(&vm);
5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981
    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)))
5982
        return -1;
5983 5984 5985 5986 5987 5988

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

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

5989
 cleanup:
5990
    virDomainObjEndAPI(&vm);
5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006
    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)))
6007
        return -1;
6008 6009 6010 6011 6012 6013 6014

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

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

6015
 cleanup:
6016
    virDomainObjEndAPI(&vm);
6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031
    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)))
6032
        return NULL;
6033 6034 6035 6036 6037 6038

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

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

6039
 cleanup:
6040
    virDomainObjEndAPI(&vm);
6041 6042 6043 6044 6045 6046 6047 6048
    return snapshot;
}

static int
testDomainHasCurrentSnapshot(virDomainPtr domain,
                             unsigned int flags)
{
    virDomainObjPtr vm;
6049
    int ret;
6050 6051 6052 6053

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6054
        return -1;
6055 6056 6057

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

6058
    virDomainObjEndAPI(&vm);
6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072
    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)))
6073
        return NULL;
6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086

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

6087
 cleanup:
6088
    virDomainObjEndAPI(&vm);
6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101
    return parent;
}

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

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
6102
        return NULL;
6103 6104 6105 6106 6107 6108 6109 6110 6111

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

6112
 cleanup:
6113
    virDomainObjEndAPI(&vm);
6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124
    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];
6125
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6126 6127 6128 6129

    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6130
        return NULL;
6131 6132 6133 6134 6135 6136

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

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

6137
    xml = virDomainSnapshotDefFormat(uuidstr, snap->def, privconn->caps,
6138 6139
                                     virDomainDefFormatConvertXMLFlags(flags),
                                     0);
6140

6141
 cleanup:
6142
    virDomainObjEndAPI(&vm);
6143 6144 6145 6146 6147 6148 6149 6150
    return xml;
}

static int
testDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6151
    int ret;
6152 6153 6154 6155

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6156
        return -1;
6157 6158 6159 6160

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

6161
    virDomainObjEndAPI(&vm);
6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175
    return ret;
}


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

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6176
        return -1;
6177

C
Cole Robinson 已提交
6178
    if (!testSnapObjFromSnapshot(vm, snapshot))
6179 6180 6181 6182
        goto cleanup;

    ret = 1;

6183
 cleanup:
6184
    virDomainObjEndAPI(&vm);
6185 6186 6187
    return ret;
}

6188 6189 6190 6191 6192 6193
static int
testDomainSnapshotAlignDisks(virDomainObjPtr vm,
                             virDomainSnapshotDefPtr def,
                             unsigned int flags)
{
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
E
Eric Blake 已提交
6194
    bool align_match = true;
6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222

    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)
{
6223
    testDriverPtr privconn = domain->conn->privateData;
6224 6225 6226 6227
    virDomainObjPtr vm = NULL;
    virDomainSnapshotDefPtr def = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr snapshot = NULL;
6228
    virObjectEventPtr event = NULL;
6229
    char *xml = NULL;
6230 6231
    bool update_current = true;
    bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
6232 6233 6234 6235 6236 6237 6238 6239
    unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;

    /*
     * DISK_ONLY: Not implemented yet
     * REUSE_EXT: Not implemented yet
     *
     * NO_METADATA: Explicitly not implemented
     *
6240
     * REDEFINE + CURRENT: Implemented
6241 6242 6243 6244 6245 6246
     * HALT: Implemented
     * QUIESCE: Nothing to do
     * ATOMIC: Nothing to do
     * LIVE: Nothing to do
     */
    virCheckFlags(
6247 6248
        VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
        VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
6249 6250 6251 6252 6253
        VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
        VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
        VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
        VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, NULL);

6254 6255 6256 6257 6258
    if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)))
        update_current = false;
    if (redefine)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;

6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273
    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;

6274
    if (redefine) {
C
Cole Robinson 已提交
6275 6276
        if (virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
                                          &update_current, flags) < 0)
6277 6278 6279 6280 6281 6282 6283
            goto cleanup;
    } else {
        if (!(def->dom = virDomainDefCopy(vm->def,
                                          privconn->caps,
                                          privconn->xmlopt,
                                          true)))
            goto cleanup;
6284

6285
        if (testDomainSnapshotAlignDisks(vm, def, flags) < 0)
6286 6287 6288
            goto cleanup;
    }

6289 6290 6291 6292
    if (!snap) {
        if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
            goto cleanup;
        def = NULL;
6293 6294
    }

6295 6296 6297 6298 6299 6300 6301 6302 6303 6304
    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);
6305
            event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
6306 6307 6308
                                    VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
        }
    }
6309 6310

    snapshot = virGetDomainSnapshot(domain, snap->def->name);
6311
 cleanup:
6312 6313 6314 6315
    VIR_FREE(xml);
    if (vm) {
        if (snapshot) {
            virDomainSnapshotObjPtr other;
6316 6317
            if (update_current)
                vm->current_snapshot = snap;
6318 6319 6320 6321 6322 6323 6324
            other = virDomainSnapshotFindByName(vm->snapshots,
                                                snap->def->parent);
            snap->parent = other;
            other->nchildren++;
            snap->sibling = other->first_child;
            other->first_child = snap;
        }
6325
        virDomainObjEndAPI(&vm);
6326
    }
6327
    testObjectEventQueue(privconn, event);
6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339
    virDomainSnapshotDefFree(def);
    return snapshot;
}


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

6340
static int
6341
testDomainSnapshotDiscardAll(void *payload,
6342 6343
                             const void *name ATTRIBUTE_UNUSED,
                             void *data)
6344 6345 6346 6347 6348 6349 6350
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapRemoveDataPtr curr = data;

    if (snap->def->current)
        curr->current = true;
    virDomainSnapshotObjListRemove(curr->vm->snapshots, snap);
6351
    return 0;
6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362
}

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

6363
static int
6364 6365 6366 6367 6368 6369 6370
testDomainSnapshotReparentChildren(void *payload,
                                   const void *name ATTRIBUTE_UNUSED,
                                   void *data)
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapReparentDataPtr rep = data;

6371
    if (rep->err < 0)
6372
        return 0;
6373 6374 6375 6376 6377 6378 6379

    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;
6380
        return 0;
6381 6382 6383 6384
    }

    if (!snap->sibling)
        rep->last = snap;
6385
    return 0;
6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414
}

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) {
6415
            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)
6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458
                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;
6459
 cleanup:
6460
    virDomainObjEndAPI(&vm);
6461 6462 6463 6464 6465 6466 6467
    return ret;
}

static int
testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                           unsigned int flags)
{
6468
    testDriverPtr privconn = snapshot->domain->conn->privateData;
6469 6470
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
6471 6472
    virObjectEventPtr event = NULL;
    virObjectEventPtr event2 = NULL;
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 6560 6561 6562 6563
    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);
6564
                event = virDomainEventLifecycleNewFromObj(vm,
6565 6566
                            VIR_DOMAIN_EVENT_STOPPED,
                            VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
6567
                testObjectEventQueue(privconn, event);
6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578
                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. */
6579
                event = virDomainEventLifecycleNewFromObj(vm,
6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592
                                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;
6593
            event = virDomainEventLifecycleNewFromObj(vm,
6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606
                                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 */
6607
                event2 = virDomainEventLifecycleNewFromObj(vm,
6608 6609 6610 6611 6612
                                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 已提交
6613
            virObjectUnref(event);
6614 6615 6616 6617
            event = NULL;

            if (was_stopped) {
                /* Transition 2 */
6618
                event = virDomainEventLifecycleNewFromObj(vm,
6619 6620 6621 6622
                                VIR_DOMAIN_EVENT_STARTED,
                                VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            } else if (was_running) {
                /* Transition 8 */
6623
                event = virDomainEventLifecycleNewFromObj(vm,
6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635
                                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);
6636
            event = virDomainEventLifecycleNewFromObj(vm,
6637 6638 6639 6640 6641 6642 6643 6644 6645
                                    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;

6646
            testObjectEventQueue(privconn, event);
6647
            event = virDomainEventLifecycleNewFromObj(vm,
6648 6649 6650
                            VIR_DOMAIN_EVENT_STARTED,
                            VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            if (paused) {
6651
                event2 = virDomainEventLifecycleNewFromObj(vm,
6652 6653 6654 6655 6656 6657 6658 6659
                                VIR_DOMAIN_EVENT_SUSPENDED,
                                VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
            }
        }
    }

    vm->current_snapshot = snap;
    ret = 0;
6660
 cleanup:
6661
    if (event) {
6662
        testObjectEventQueue(privconn, event);
6663
        testObjectEventQueue(privconn, event2);
C
Cole Robinson 已提交
6664
    } else {
C
Cédric Bosdonnat 已提交
6665
        virObjectUnref(event2);
6666
    }
6667
    virDomainObjEndAPI(&vm);
6668 6669 6670 6671 6672

    return ret;
}


6673

6674
static virHypervisorDriver testHypervisorDriver = {
6675
    .name = "Test",
6676 6677 6678
    .connectOpen = testConnectOpen, /* 0.1.1 */
    .connectClose = testConnectClose, /* 0.1.1 */
    .connectGetVersion = testConnectGetVersion, /* 0.1.1 */
6679
    .connectGetHostname = testConnectGetHostname, /* 0.6.3 */
6680
    .connectGetMaxVcpus = testConnectGetMaxVcpus, /* 0.3.2 */
6681
    .nodeGetInfo = testNodeGetInfo, /* 0.1.1 */
6682 6683 6684 6685
    .connectGetCapabilities = testConnectGetCapabilities, /* 0.2.1 */
    .connectListDomains = testConnectListDomains, /* 0.1.1 */
    .connectNumOfDomains = testConnectNumOfDomains, /* 0.1.1 */
    .connectListAllDomains = testConnectListAllDomains, /* 0.9.13 */
6686
    .domainCreateXML = testDomainCreateXML, /* 0.1.4 */
6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700
    .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 */
6701 6702
    .domainGetState = testDomainGetState, /* 0.9.2 */
    .domainSave = testDomainSave, /* 0.3.2 */
6703
    .domainSaveFlags = testDomainSaveFlags, /* 0.9.4 */
6704
    .domainRestore = testDomainRestore, /* 0.3.2 */
6705
    .domainRestoreFlags = testDomainRestoreFlags, /* 0.9.4 */
6706
    .domainCoreDump = testDomainCoreDump, /* 0.3.2 */
6707
    .domainCoreDumpWithFormat = testDomainCoreDumpWithFormat, /* 1.2.3 */
6708
    .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */
6709 6710 6711 6712
    .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */
    .domainGetVcpusFlags = testDomainGetVcpusFlags, /* 0.8.5 */
    .domainPinVcpu = testDomainPinVcpu, /* 0.7.3 */
    .domainGetVcpus = testDomainGetVcpus, /* 0.7.3 */
6713
    .domainGetVcpuPinInfo = testDomainGetVcpuPinInfo, /* 1.2.18 */
6714 6715
    .domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
    .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
6716 6717
    .connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
    .connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
6718 6719 6720
    .domainCreate = testDomainCreate, /* 0.1.11 */
    .domainCreateWithFlags = testDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = testDomainDefineXML, /* 0.1.11 */
6721
    .domainDefineXMLFlags = testDomainDefineXMLFlags, /* 1.2.12 */
6722
    .domainUndefine = testDomainUndefine, /* 0.1.11 */
6723
    .domainUndefineFlags = testDomainUndefineFlags, /* 0.9.4 */
6724 6725 6726
    .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
    .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
    .domainGetSchedulerType = testDomainGetSchedulerType, /* 0.3.2 */
6727 6728 6729 6730
    .domainGetSchedulerParameters = testDomainGetSchedulerParameters, /* 0.3.2 */
    .domainGetSchedulerParametersFlags = testDomainGetSchedulerParametersFlags, /* 0.9.2 */
    .domainSetSchedulerParameters = testDomainSetSchedulerParameters, /* 0.3.2 */
    .domainSetSchedulerParametersFlags = testDomainSetSchedulerParametersFlags, /* 0.9.2 */
6731 6732 6733
    .domainBlockStats = testDomainBlockStats, /* 0.7.0 */
    .domainInterfaceStats = testDomainInterfaceStats, /* 0.7.0 */
    .nodeGetCellsFreeMemory = testNodeGetCellsFreeMemory, /* 0.4.2 */
6734 6735 6736 6737
    .connectDomainEventRegister = testConnectDomainEventRegister, /* 0.6.0 */
    .connectDomainEventDeregister = testConnectDomainEventDeregister, /* 0.6.0 */
    .connectIsEncrypted = testConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = testConnectIsSecure, /* 0.7.3 */
6738 6739 6740
    .domainIsActive = testDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = testDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = testDomainIsUpdated, /* 0.8.6 */
6741 6742 6743
    .connectDomainEventRegisterAny = testConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = testConnectDomainEventDeregisterAny, /* 0.8.0 */
    .connectIsAlive = testConnectIsAlive, /* 0.9.8 */
6744
    .nodeGetCPUMap = testNodeGetCPUMap, /* 1.0.0 */
6745
    .domainScreenshot = testDomainScreenshot, /* 1.0.5 */
6746 6747
    .domainGetMetadata = testDomainGetMetadata, /* 1.1.3 */
    .domainSetMetadata = testDomainSetMetadata, /* 1.1.3 */
6748
    .connectGetCPUModelNames = testConnectGetCPUModelNames, /* 1.1.3 */
6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765
    .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 */
6766 6767 6768
    .domainSnapshotCreateXML = testDomainSnapshotCreateXML, /* 1.1.4 */
    .domainRevertToSnapshot = testDomainRevertToSnapshot, /* 1.1.4 */
    .domainSnapshotDelete = testDomainSnapshotDelete, /* 1.1.4 */
6769

E
Eric Blake 已提交
6770
    .connectBaselineCPU = testConnectBaselineCPU, /* 1.2.0 */
6771 6772 6773
};

static virNetworkDriver testNetworkDriver = {
6774 6775 6776 6777 6778
    .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 */
6779 6780
    .connectNetworkEventRegisterAny = testConnectNetworkEventRegisterAny, /* 1.2.1 */
    .connectNetworkEventDeregisterAny = testConnectNetworkEventDeregisterAny, /* 1.2.1 */
6781 6782 6783 6784
    .networkLookupByUUID = testNetworkLookupByUUID, /* 0.3.2 */
    .networkLookupByName = testNetworkLookupByName, /* 0.3.2 */
    .networkCreateXML = testNetworkCreateXML, /* 0.3.2 */
    .networkDefineXML = testNetworkDefineXML, /* 0.3.2 */
6785
    .networkUndefine = testNetworkUndefine, /* 0.3.2 */
6786
    .networkUpdate = testNetworkUpdate, /* 0.10.2 */
6787
    .networkCreate = testNetworkCreate, /* 0.3.2 */
6788 6789 6790 6791 6792 6793 6794
    .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 */
6795 6796
};

L
Laine Stump 已提交
6797
static virInterfaceDriver testInterfaceDriver = {
6798 6799 6800 6801 6802 6803
    .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 */
6804 6805 6806 6807 6808 6809
    .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 */
6810 6811 6812
    .interfaceChangeBegin = testInterfaceChangeBegin,   /* 0.9.2 */
    .interfaceChangeCommit = testInterfaceChangeCommit,  /* 0.9.2 */
    .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */
L
Laine Stump 已提交
6813 6814 6815
};


6816
static virStorageDriver testStorageDriver = {
6817 6818 6819 6820 6821 6822
    .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 */
6823 6824
    .connectStoragePoolEventRegisterAny = testConnectStoragePoolEventRegisterAny, /* 2.0.0 */
    .connectStoragePoolEventDeregisterAny = testConnectStoragePoolEventDeregisterAny, /* 2.0.0 */
6825 6826 6827
    .storagePoolLookupByName = testStoragePoolLookupByName, /* 0.5.0 */
    .storagePoolLookupByUUID = testStoragePoolLookupByUUID, /* 0.5.0 */
    .storagePoolLookupByVolume = testStoragePoolLookupByVolume, /* 0.5.0 */
6828 6829
    .storagePoolCreateXML = testStoragePoolCreateXML, /* 0.5.0 */
    .storagePoolDefineXML = testStoragePoolDefineXML, /* 0.5.0 */
6830 6831
    .storagePoolBuild = testStoragePoolBuild, /* 0.5.0 */
    .storagePoolUndefine = testStoragePoolUndefine, /* 0.5.0 */
6832
    .storagePoolCreate = testStoragePoolCreate, /* 0.5.0 */
6833 6834 6835 6836 6837 6838 6839
    .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 */
6840
    .storagePoolNumOfVolumes = testStoragePoolNumOfVolumes, /* 0.5.0 */
6841 6842 6843
    .storagePoolListVolumes = testStoragePoolListVolumes, /* 0.5.0 */
    .storagePoolListAllVolumes = testStoragePoolListAllVolumes, /* 0.10.2 */

6844 6845 6846 6847 6848 6849 6850 6851 6852
    .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 */
6853 6854
    .storagePoolIsActive = testStoragePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = testStoragePoolIsPersistent, /* 0.7.3 */
6855 6856
};

6857
static virNodeDeviceDriver testNodeDeviceDriver = {
6858 6859
    .connectNodeDeviceEventRegisterAny = testConnectNodeDeviceEventRegisterAny, /* 2.2.0 */
    .connectNodeDeviceEventDeregisterAny = testConnectNodeDeviceEventDeregisterAny, /* 2.2.0 */
6860 6861 6862 6863 6864 6865 6866 6867 6868
    .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 */
6869 6870
};

6871 6872 6873 6874 6875 6876 6877 6878
static virConnectDriver testConnectDriver = {
    .hypervisorDriver = &testHypervisorDriver,
    .interfaceDriver = &testInterfaceDriver,
    .networkDriver = &testNetworkDriver,
    .nodeDeviceDriver = &testNodeDeviceDriver,
    .nwfilterDriver = NULL,
    .secretDriver = NULL,
    .storageDriver = &testStorageDriver,
6879 6880
};

6881 6882 6883 6884 6885 6886 6887 6888
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
6889 6890
    return virRegisterConnectDriver(&testConnectDriver,
                                    false);
6891
}