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

63 64
#define VIR_FROM_THIS VIR_FROM_TEST

65 66
VIR_LOG_INIT("test.test_driver");

67 68 69 70 71 72 73 74 75
/* Driver specific info to carry with a domain */
struct _testDomainObjPrivate {
    virVcpuInfoPtr vcpu_infos;

    unsigned char *cpumaps;
};
typedef struct _testDomainObjPrivate testDomainObjPrivate;
typedef struct _testDomainObjPrivate *testDomainObjPrivatePtr;

76 77 78 79 80
#define MAX_CPUS 128

struct _testCell {
    unsigned long mem;
    int numCpus;
81
    virCapsHostNUMACellCPU cpus[MAX_CPUS];
82 83 84 85 86
};
typedef struct _testCell testCell;
typedef struct _testCell *testCellPtr;

#define MAX_CELLS 128
87

88 89 90 91 92 93 94
struct _testAuth {
    char *username;
    char *password;
};
typedef struct _testAuth testAuth;
typedef struct _testAuth *testAuthPtr;

95
struct _testConn {
96
    virMutex lock;
97

E
Eric Blake 已提交
98
    char *path;
99
    int nextDomID;
100
    virCapsPtr caps;
101
    virDomainXMLOptionPtr xmlopt;
102
    virNodeInfo nodeInfo;
103
    virDomainObjListPtr domains;
104
    virNetworkObjListPtr networks;
L
Laine Stump 已提交
105
    virInterfaceObjList ifaces;
106 107
    bool transaction_running;
    virInterfaceObjList backupIfaces;
C
Cole Robinson 已提交
108
    virStoragePoolObjList pools;
109
    virNodeDeviceObjList devs;
110 111
    int numCells;
    testCell cells[MAX_CELLS];
112 113
    size_t numAuths;
    testAuthPtr auths;
114

115
    virObjectEventStatePtr eventState;
116 117
};
typedef struct _testConn testConn;
118
typedef testConn *testConnPtr;
119

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

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

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

138

139
static int testConnectClose(virConnectPtr conn);
140
static void testObjectEventQueue(testConnPtr driver,
141
                                 virObjectEventPtr event);
142

143 144
static void testDriverLock(testConnPtr driver)
{
145
    virMutexLock(&driver->lock);
146 147 148 149
}

static void testDriverUnlock(testConnPtr driver)
{
150
    virMutexUnlock(&driver->lock);
151 152
}

153 154 155 156 157 158 159 160 161 162 163 164 165 166
static void *testDomainObjPrivateAlloc(void)
{
    testDomainObjPrivatePtr priv;

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

    return priv;
}

static void testDomainObjPrivateFree(void *data)
{
    testDomainObjPrivatePtr priv = data;

D
Daniel P. Berrange 已提交
167
    VIR_FREE(priv->vcpu_infos);
168 169 170 171
    VIR_FREE(priv->cpumaps);
    VIR_FREE(priv);
}

172 173 174 175 176 177
#define TEST_NAMESPACE_HREF "http://libvirt.org/schemas/domain/test/1.0"

typedef struct _testDomainNamespaceDef testDomainNamespaceDef;
typedef testDomainNamespaceDef *testDomainNamespaceDefPtr;
struct _testDomainNamespaceDef {
    int runstate;
178
    bool transient;
C
Cole Robinson 已提交
179
    bool hasManagedSave;
180 181 182

    unsigned int num_snap_nodes;
    xmlNodePtr *snap_nodes;
183 184 185 186 187 188
};

static void
testDomainDefNamespaceFree(void *data)
{
    testDomainNamespaceDefPtr nsdata = data;
189 190 191 192 193 194 195 196 197
    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);
198 199 200 201 202 203 204 205 206 207
    VIR_FREE(nsdata);
}

static int
testDomainDefNamespaceParse(xmlDocPtr xml ATTRIBUTE_UNUSED,
                            xmlNodePtr root ATTRIBUTE_UNUSED,
                            xmlXPathContextPtr ctxt,
                            void **data)
{
    testDomainNamespaceDefPtr nsdata = NULL;
208 209 210
    xmlNodePtr *nodes = NULL;
    int tmp, n;
    size_t i;
211 212 213 214 215 216 217 218 219 220 221 222 223
    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;

224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
    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);

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

257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
    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;
    }

273 274 275 276 277
    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 已提交
278 279 280 281 282
    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;
    }
283

284 285 286
    *data = nsdata;
    return 0;

287
 error:
288
    VIR_FREE(nodes);
289 290 291
    testDomainDefNamespaceFree(nsdata);
    return -1;
}
292

293
static virDomainXMLOptionPtr
294 295
testBuildXMLConfig(void)
{
296 297 298 299 300 301 302 303 304 305 306 307
    virDomainXMLPrivateDataCallbacks priv = {
        .alloc = testDomainObjPrivateAlloc,
        .free = testDomainObjPrivateFree
    };

    /* All our XML extensions are input only, so we only need to parse */
    virDomainXMLNamespace ns = {
        .parse = testDomainDefNamespaceParse,
        .free = testDomainDefNamespaceFree,
    };

    return virDomainXMLOptionNew(NULL, &priv, &ns);
308 309 310
}


311
static virCapsPtr
312 313
testBuildCapabilities(virConnectPtr conn)
{
314
    testConnPtr privconn = conn->privateData;
315 316
    virCapsPtr caps;
    virCapsGuestPtr guest;
317 318
    int guest_types[] = { VIR_DOMAIN_OSTYPE_HVM,
                          VIR_DOMAIN_OSTYPE_XEN };
319
    size_t i;
320

321
    if ((caps = virCapabilitiesNew(VIR_ARCH_I686, false, false)) == NULL)
322
        goto error;
323

324
    if (virCapabilitiesAddHostFeature(caps, "pae") < 0)
325
        goto error;
326
    if (virCapabilitiesAddHostFeature(caps, "nonpae") < 0)
327
        goto error;
328

329
    for (i = 0; i < privconn->numCells; i++) {
330 331 332
        virCapsHostNUMACellCPUPtr cpu_cells;

        if (VIR_ALLOC_N(cpu_cells, privconn->cells[i].numCpus) < 0)
333
            goto error;
334 335 336 337 338

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


339 340
        if (virCapabilitiesAddHostNUMACell(caps, i, 0,
                                           privconn->cells[i].numCpus,
M
Michal Privoznik 已提交
341
                                           cpu_cells, 0, NULL, 0, NULL) < 0)
342
            goto error;
343 344
    }

345
    for (i = 0; i < ARRAY_CARDINALITY(guest_types); i++) {
346 347
        if ((guest = virCapabilitiesAddGuest(caps,
                                             guest_types[i],
348
                                             VIR_ARCH_I686,
349 350 351 352
                                             TEST_EMULATOR,
                                             NULL,
                                             0,
                                             NULL)) == NULL)
353
            goto error;
354

355
        if (virCapabilitiesAddGuestDomain(guest,
356
                                          VIR_DOMAIN_VIRT_TEST,
357 358 359 360
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
361
            goto error;
362

363
        if (virCapabilitiesAddGuestFeature(guest, "pae", true, true) == NULL)
364
            goto error;
365
        if (virCapabilitiesAddGuestFeature(guest, "nonpae", true, true) == NULL)
366
            goto error;
367 368
    }

369 370
    caps->host.nsecModels = 1;
    if (VIR_ALLOC_N(caps->host.secModels, caps->host.nsecModels) < 0)
371
        goto error;
372 373
    if (VIR_STRDUP(caps->host.secModels[0].model, "testSecurity") < 0)
        goto error;
374

375 376
    if (VIR_STRDUP(caps->host.secModels[0].doi, "") < 0)
        goto error;
377

378
    return caps;
379

380
 error:
381
    virObjectUnref(caps);
382
    return NULL;
383 384
}

385

386 387 388
static const char *defaultDomainXML =
"<domain type='test'>"
"  <name>test</name>"
389
"  <uuid>6695eb01-f6a4-8304-79aa-97f2502e193f</uuid>"
390 391 392 393 394 395 396
"  <memory>8388608</memory>"
"  <currentMemory>2097152</currentMemory>"
"  <vcpu>2</vcpu>"
"  <os>"
"    <type>hvm</type>"
"  </os>"
"</domain>";
397 398


399 400 401
static const char *defaultNetworkXML =
"<network>"
"  <name>default</name>"
402
"  <uuid>dd8fe884-6c02-601e-7551-cca97df1c5df</uuid>"
403
"  <bridge name='virbr0'/>"
404 405 406
"  <forward/>"
"  <ip address='192.168.122.1' netmask='255.255.255.0'>"
"    <dhcp>"
407
"      <range start='192.168.122.2' end='192.168.122.254'/>"
408 409 410
"    </dhcp>"
"  </ip>"
"</network>";
411

L
Laine Stump 已提交
412 413 414 415 416 417 418 419 420 421 422
static const char *defaultInterfaceXML =
"<interface type=\"ethernet\" name=\"eth1\">"
"  <start mode=\"onboot\"/>"
"  <mac address=\"aa:bb:cc:dd:ee:ff\"/>"
"  <mtu size=\"1492\"/>"
"  <protocol family=\"ipv4\">"
"    <ip address=\"192.168.0.5\" prefix=\"24\"/>"
"    <route gateway=\"192.168.0.1\"/>"
"  </protocol>"
"</interface>";

C
Cole Robinson 已提交
423 424 425
static const char *defaultPoolXML =
"<pool type='dir'>"
"  <name>default-pool</name>"
426
"  <uuid>dfe224cb-28fb-8dd0-c4b2-64eb3f0f4566</uuid>"
C
Cole Robinson 已提交
427 428 429 430 431
"  <target>"
"    <path>/default-pool</path>"
"  </target>"
"</pool>";

432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
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";

455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
static const char *defaultNodeXML =
"<device>"
"  <name>computer</name>"
"  <capability type='system'>"
"    <hardware>"
"      <vendor>Libvirt</vendor>"
"      <version>Test driver</version>"
"      <serial>123456</serial>"
"      <uuid>11111111-2222-3333-4444-555555555555</uuid>"
"    </hardware>"
"    <firmware>"
"      <vendor>Libvirt</vendor>"
"      <version>Test Driver</version>"
"      <release_date>01/22/2007</release_date>"
"    </firmware>"
"  </capability>"
"</device>";

473
static const unsigned long long defaultPoolCap = (100 * 1024 * 1024 * 1024ull);
474
static const unsigned long long defaultPoolAlloc;
C
Cole Robinson 已提交
475

476
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool);
477
static int testNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
478

479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
static virDomainObjPtr
testDomObjFromDomain(virDomainPtr domain)
{
    virDomainObjPtr vm;
    testConnPtr driver = domain->conn->privateData;
    char uuidstr[VIR_UUID_STRING_BUFLEN];

    testDriverLock(driver);
    vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
    if (!vm) {
        virUUIDFormat(domain->uuid, uuidstr);
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching uuid '%s' (%s)"),
                       uuidstr, domain->name);
    }

    testDriverUnlock(driver);
    return vm;
}

499
static char *
500 501
testDomainGenerateIfname(virDomainDefPtr domdef)
{
502
    int maxif = 1024;
503 504
    int ifctr;
    size_t i;
505 506 507 508 509

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

510
        if (virAsprintf(&ifname, "testnet%d", ifctr) < 0)
511 512 513
            return NULL;

        /* Generate network interface names */
514
        for (i = 0; i < domdef->nnets; i++) {
515
            if (domdef->nets[i]->ifname &&
516
                STREQ(domdef->nets[i]->ifname, ifname)) {
517 518 519 520 521 522 523
                found = 1;
                break;
            }
        }

        if (!found)
            return ifname;
524
        VIR_FREE(ifname);
525 526
    }

527 528
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Exceeded max iface limit %d"), maxif);
529 530 531
    return NULL;
}

532
static int
533
testDomainGenerateIfnames(virDomainDefPtr domdef)
534
{
535
    size_t i = 0;
536 537 538 539 540 541

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

542
        ifname = testDomainGenerateIfname(domdef);
543
        if (!ifname)
544
            return -1;
545 546 547 548

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

549
    return 0;
550 551
}

552 553
/* Helper to update info for a single VCPU */
static int
554
testDomainUpdateVCPU(virDomainObjPtr dom,
555 556 557 558 559 560 561
                     int vcpu,
                     int maplen,
                     int maxcpu)
{
    testDomainObjPrivatePtr privdata = dom->privateData;
    virVcpuInfoPtr info = &privdata->vcpu_infos[vcpu];
    unsigned char *cpumap = VIR_GET_CPUMAP(privdata->cpumaps, maplen, vcpu);
562
    size_t j;
H
Hu Tao 已提交
563
    bool cpu;
564 565 566 567 568 569 570 571 572 573 574

    memset(info, 0, sizeof(virVcpuInfo));
    memset(cpumap, 0, maplen);

    info->number    = vcpu;
    info->state     = VIR_VCPU_RUNNING;
    info->cpuTime   = 5000000;
    info->cpu       = 0;

    if (dom->def->cpumask) {
        for (j = 0; j < maxcpu && j < VIR_DOMAIN_CPUMASK_LEN; ++j) {
H
Hu Tao 已提交
575 576 577
            if (virBitmapGetBit(dom->def->cpumask, j, &cpu) < 0)
                return -1;
            if (cpu) {
578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
                VIR_USE_CPU(cpumap, j);
                info->cpu = j;
            }
        }
    } else {
        for (j = 0; j < maxcpu; ++j) {
            if ((j % 3) == 0) {
                /* Mark of every third CPU as usable */
                VIR_USE_CPU(cpumap, j);
                info->cpu = j;
            }
        }
    }

    return 0;
}

/*
 * Update domain VCPU amount and info
 *
 * @conn: virConnectPtr
 * @dom : domain needing updates
 * @nvcpus: New amount of vcpus for the domain
 * @clear_all: If true, rebuild info for ALL vcpus, not just newly added vcpus
 */
static int
604
testDomainUpdateVCPUs(testConnPtr privconn,
605 606 607 608 609
                      virDomainObjPtr dom,
                      int nvcpus,
                      unsigned int clear_all)
{
    testDomainObjPrivatePtr privdata = dom->privateData;
610 611
    size_t i;
    int ret = -1;
612 613 614 615 616
    int cpumaplen, maxcpu;

    maxcpu  = VIR_NODEINFO_MAXCPUS(privconn->nodeInfo);
    cpumaplen = VIR_CPU_MAPLEN(maxcpu);

617
    if (VIR_REALLOC_N(privdata->vcpu_infos, nvcpus) < 0)
618 619
        goto cleanup;

620
    if (VIR_REALLOC_N(privdata->cpumaps, nvcpus * cpumaplen) < 0)
621 622 623 624 625
        goto cleanup;

    /* Set running VCPU and cpumap state */
    if (clear_all) {
        for (i = 0; i < nvcpus; ++i)
626
            if (testDomainUpdateVCPU(dom, i, cpumaplen, maxcpu) < 0)
627 628 629 630 631
                goto cleanup;

    } else if (nvcpus > dom->def->vcpus) {
        /* VCPU amount has grown, populate info for the new vcpus */
        for (i = dom->def->vcpus; i < nvcpus; ++i)
632
            if (testDomainUpdateVCPU(dom, i, cpumaplen, maxcpu) < 0)
633 634 635
                goto cleanup;
    }

636
    dom->def->vcpus = nvcpus;
637
    ret = 0;
638
 cleanup:
639 640 641
    return ret;
}

642 643
static void
testDomainShutdownState(virDomainPtr domain,
J
Jiri Denemark 已提交
644 645
                        virDomainObjPtr privdom,
                        virDomainShutoffReason reason)
646 647 648 649 650 651 652
{
    if (privdom->newDef) {
        virDomainDefFree(privdom->def);
        privdom->def = privdom->newDef;
        privdom->newDef = NULL;
    }

J
Jiri Denemark 已提交
653
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF, reason);
654 655 656 657 658
    privdom->def->id = -1;
    if (domain)
        domain->id = -1;
}

659
/* Set up domain runtime state */
660
static int
661
testDomainStartState(testConnPtr privconn,
J
Jiri Denemark 已提交
662 663
                     virDomainObjPtr dom,
                     virDomainRunningReason reason)
664
{
665
    int ret = -1;
666

667
    if (testDomainUpdateVCPUs(privconn, dom, dom->def->vcpus, 1) < 0)
668 669
        goto cleanup;

J
Jiri Denemark 已提交
670
    virDomainObjSetState(dom, VIR_DOMAIN_RUNNING, reason);
671 672
    dom->def->id = privconn->nextDomID++;

673
    if (virDomainObjSetDefTransient(privconn->caps,
674
                                    privconn->xmlopt,
675
                                    dom, false) < 0) {
676 677 678
        goto cleanup;
    }

C
Cole Robinson 已提交
679
    dom->hasManagedSave = false;
680
    ret = 0;
681
 cleanup:
682
    if (ret < 0)
J
Jiri Denemark 已提交
683
        testDomainShutdownState(NULL, dom, VIR_DOMAIN_SHUTOFF_FAILED);
684
    return ret;
685
}
686

687 688 689 690 691 692 693

/* 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)
{
694
    int u;
695
    testConnPtr privconn = &defaultConn;
696 697 698 699
    virDomainDefPtr domdef = NULL;
    virDomainObjPtr domobj = NULL;
    virNetworkDefPtr netdef = NULL;
    virNetworkObjPtr netobj = NULL;
L
Laine Stump 已提交
700 701
    virInterfaceDefPtr interfacedef = NULL;
    virInterfaceObjPtr interfaceobj = NULL;
C
Cole Robinson 已提交
702 703
    virStoragePoolDefPtr pooldef = NULL;
    virStoragePoolObjPtr poolobj = NULL;
704 705
    virNodeDeviceDefPtr nodedef = NULL;
    virNodeDeviceObjPtr nodeobj = NULL;
706

707 708 709 710 711 712 713
    virMutexLock(&defaultLock);
    if (defaultConnections++) {
        conn->privateData = &defaultConn;
        virMutexUnlock(&defaultLock);
        return VIR_DRV_OPEN_SUCCESS;
    }

714
    if (virMutexInit(&privconn->lock) < 0) {
715 716
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot initialize mutex"));
717 718
        defaultConnections--;
        virMutexUnlock(&defaultLock);
719 720 721 722
        return VIR_DRV_OPEN_ERROR;
    }

    conn->privateData = privconn;
723

724
    if (!(privconn->eventState = virObjectEventStateNew()))
725 726
        goto error;

727
    if (!(privconn->domains = virDomainObjListNew()) ||
728
        !(privconn->networks = virNetworkObjListNew()))
729 730
        goto error;

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

733
    /* Numa setup */
734 735 736 737 738
    privconn->numCells = 2;
    for (u = 0; u < 2; ++u) {
        privconn->cells[u].numCpus = 8;
        privconn->cells[u].mem = (u + 1) * 2048 * 1024;
    }
739
    for (u = 0; u < 16; u++) {
740
        virBitmapPtr siblings = virBitmapNew(16);
741
        if (!siblings)
742 743 744 745 746 747
            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;
748 749
    }

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

753
    if (!(privconn->xmlopt = testBuildXMLConfig()))
754 755
        goto error;

756 757
    privconn->nextDomID = 1;

758 759
    if (!(domdef = virDomainDefParseString(defaultDomainXML,
                                           privconn->caps,
760
                                           privconn->xmlopt,
761
                                           VIR_DOMAIN_DEF_PARSE_INACTIVE)))
762
        goto error;
M
Matthias Bolte 已提交
763

764
    if (testDomainGenerateIfnames(domdef) < 0)
765
        goto error;
766
    if (!(domobj = virDomainObjListAdd(privconn->domains,
767
                                       domdef,
768
                                       privconn->xmlopt,
769
                                       0, NULL)))
770 771
        goto error;
    domdef = NULL;
772

773
    domobj->persistent = 1;
774 775
    if (testDomainStartState(privconn, domobj,
                             VIR_DOMAIN_RUNNING_BOOTED) < 0) {
776
        virObjectUnlock(domobj);
777 778 779
        goto error;
    }

780
    virObjectUnlock(domobj);
781

782
    if (!(netdef = virNetworkDefParseString(defaultNetworkXML)))
783
        goto error;
784
    if (!(netobj = virNetworkAssignDef(privconn->networks, netdef, 0))) {
785 786 787 788
        virNetworkDefFree(netdef);
        goto error;
    }
    netobj->active = 1;
789
    virNetworkObjEndAPI(&netobj);
790

791
    if (!(interfacedef = virInterfaceDefParseString(defaultInterfaceXML)))
L
Laine Stump 已提交
792
        goto error;
793
    if (!(interfaceobj = virInterfaceAssignDef(&privconn->ifaces, interfacedef))) {
L
Laine Stump 已提交
794 795 796 797 798 799
        virInterfaceDefFree(interfacedef);
        goto error;
    }
    interfaceobj->active = 1;
    virInterfaceObjUnlock(interfaceobj);

800
    if (!(pooldef = virStoragePoolDefParseString(defaultPoolXML)))
C
Cole Robinson 已提交
801 802
        goto error;

803
    if (!(poolobj = virStoragePoolObjAssignDef(&privconn->pools,
C
Cole Robinson 已提交
804 805 806 807
                                               pooldef))) {
        virStoragePoolDefFree(pooldef);
        goto error;
    }
808

809
    if (testStoragePoolObjSetDefaults(poolobj) == -1) {
810
        virStoragePoolObjUnlock(poolobj);
C
Cole Robinson 已提交
811
        goto error;
812
    }
C
Cole Robinson 已提交
813
    poolobj->active = 1;
814
    virStoragePoolObjUnlock(poolobj);
C
Cole Robinson 已提交
815

816
    /* Init default node device */
817
    if (!(nodedef = virNodeDeviceDefParseString(defaultNodeXML, 0, NULL)))
818
        goto error;
819
    if (!(nodeobj = virNodeDeviceAssignDef(&privconn->devs,
820 821 822 823 824 825
                                           nodedef))) {
        virNodeDeviceDefFree(nodedef);
        goto error;
    }
    virNodeDeviceObjUnlock(nodeobj);

826
    virMutexUnlock(&defaultLock);
827

828 829
    return VIR_DRV_OPEN_SUCCESS;

830
 error:
831
    virObjectUnref(privconn->domains);
832
    virObjectUnref(privconn->networks);
L
Laine Stump 已提交
833
    virInterfaceObjListFree(&privconn->ifaces);
C
Cole Robinson 已提交
834
    virStoragePoolObjListFree(&privconn->pools);
835
    virNodeDeviceObjListFree(&privconn->devs);
836
    virObjectUnref(privconn->caps);
837
    virObjectEventStateFree(privconn->eventState);
838
    virMutexDestroy(&privconn->lock);
839
    conn->privateData = NULL;
840
    virDomainDefFree(domdef);
841 842
    defaultConnections--;
    virMutexUnlock(&defaultLock);
843
    return VIR_DRV_OPEN_ERROR;
844 845 846 847
}


static char *testBuildFilename(const char *relativeTo,
848 849
                               const char *filename)
{
850 851
    char *offset;
    int baseLen;
852 853
    char *ret;

854
    if (!filename || filename[0] == '\0')
855
        return NULL;
856 857 858 859
    if (filename[0] == '/') {
        ignore_value(VIR_STRDUP(ret, filename));
        return ret;
    }
860

861
    offset = strrchr(relativeTo, '/');
862
    if ((baseLen = (offset-relativeTo+1))) {
863
        char *absFile;
C
Chris Lalancette 已提交
864 865
        int totalLen = baseLen + strlen(filename) + 1;
        if (VIR_ALLOC_N(absFile, totalLen) < 0)
866
            return NULL;
C
Chris Lalancette 已提交
867 868 869 870
        if (virStrncpy(absFile, relativeTo, baseLen, totalLen) == NULL) {
            VIR_FREE(absFile);
            return NULL;
        }
871 872 873
        strcat(absFile, filename);
        return absFile;
    } else {
874 875
        ignore_value(VIR_STRDUP(ret, filename));
        return ret;
876
    }
877 878
}

C
Cole Robinson 已提交
879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909
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;
    }

910
 error:
C
Cole Robinson 已提交
911 912 913 914 915
    xmlFreeDoc(doc);
    VIR_FREE(absFile);
    return ret;
}

916 917 918
static int
testParseNodeInfo(virNodeInfoPtr nodeInfo, xmlXPathContextPtr ctxt)
{
919
    char *str;
920 921
    long l;
    int ret;
922

923
    ret = virXPathLong("string(/node/cpu/nodes[1])", ctxt, &l);
924 925 926
    if (ret == 0) {
        nodeInfo->nodes = l;
    } else if (ret == -2) {
927 928
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu nodes value"));
929
        goto error;
930
    }
931

932
    ret = virXPathLong("string(/node/cpu/sockets[1])", ctxt, &l);
933 934 935
    if (ret == 0) {
        nodeInfo->sockets = l;
    } else if (ret == -2) {
936 937
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu sockets value"));
938
        goto error;
939
    }
940

941
    ret = virXPathLong("string(/node/cpu/cores[1])", ctxt, &l);
942 943 944
    if (ret == 0) {
        nodeInfo->cores = l;
    } else if (ret == -2) {
945 946
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu cores value"));
947
        goto error;
948 949
    }

950
    ret = virXPathLong("string(/node/cpu/threads[1])", ctxt, &l);
951 952 953
    if (ret == 0) {
        nodeInfo->threads = l;
    } else if (ret == -2) {
954 955
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu threads value"));
956
        goto error;
957
    }
958

959 960
    nodeInfo->cpus = (nodeInfo->cores * nodeInfo->threads *
                      nodeInfo->sockets * nodeInfo->nodes);
961
    ret = virXPathLong("string(/node/cpu/active[1])", ctxt, &l);
962
    if (ret == 0) {
963
        if (l < nodeInfo->cpus)
964
            nodeInfo->cpus = l;
965
    } else if (ret == -2) {
966 967
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu active value"));
968
        goto error;
969
    }
970
    ret = virXPathLong("string(/node/cpu/mhz[1])", ctxt, &l);
971 972 973
    if (ret == 0) {
        nodeInfo->mhz = l;
    } else if (ret == -2) {
974 975
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu mhz value"));
976
        goto error;
977 978
    }

979
    str = virXPathString("string(/node/cpu/model[1])", ctxt);
980
    if (str != NULL) {
C
Chris Lalancette 已提交
981
        if (virStrcpyStatic(nodeInfo->model, str) == NULL) {
982 983
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Model %s too big for destination"), str);
C
Chris Lalancette 已提交
984 985 986
            VIR_FREE(str);
            goto error;
        }
987
        VIR_FREE(str);
988 989
    }

990
    ret = virXPathLong("string(/node/memory[1])", ctxt, &l);
991 992 993
    if (ret == 0) {
        nodeInfo->memory = l;
    } else if (ret == -2) {
994 995
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node memory value"));
996
        goto error;
997
    }
998

999
    return 0;
1000
 error:
1001 1002 1003
    return -1;
}

1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055
static int
testParseDomainSnapshots(testConnPtr privconn,
                         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;
1056
 error:
1057 1058 1059
    return ret;
}

1060
static int
C
Cole Robinson 已提交
1061 1062 1063
testParseDomains(testConnPtr privconn,
                 const char *file,
                 xmlXPathContextPtr ctxt)
1064 1065 1066 1067 1068 1069 1070
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virDomainObjPtr obj;

    num = virXPathNodeSet("/node/domain", ctxt, &nodes);
1071
    if (num < 0)
1072 1073
        goto error;

1074
    for (i = 0; i < num; i++) {
1075
        virDomainDefPtr def;
1076
        testDomainNamespaceDefPtr nsdata;
C
Cole Robinson 已提交
1077 1078 1079 1080 1081 1082
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file, "domain");
        if (!node)
            goto error;

        def = virDomainDefParseNode(ctxt->doc, node,
                                    privconn->caps, privconn->xmlopt,
1083
                                    VIR_DOMAIN_DEF_PARSE_INACTIVE);
C
Cole Robinson 已提交
1084 1085
        if (!def)
            goto error;
1086

1087
        if (testDomainGenerateIfnames(def) < 0 ||
1088
            !(obj = virDomainObjListAdd(privconn->domains,
1089
                                        def,
1090
                                        privconn->xmlopt,
1091
                                        0, NULL))) {
1092
            virDomainDefFree(def);
1093 1094
            goto error;
        }
1095

1096 1097 1098 1099 1100
        if (testParseDomainSnapshots(privconn, obj, file, ctxt) < 0) {
            virObjectUnlock(obj);
            goto error;
        }

1101
        nsdata = def->namespaceData;
1102
        obj->persistent = !nsdata->transient;
C
Cole Robinson 已提交
1103
        obj->hasManagedSave = nsdata->hasManagedSave;
1104 1105 1106 1107 1108 1109 1110 1111 1112

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

1116
        virObjectUnlock(obj);
1117
    }
1118

1119
    ret = 0;
1120
 error:
1121 1122 1123 1124 1125
    VIR_FREE(nodes);
    return ret;
}

static int
C
Cole Robinson 已提交
1126 1127 1128
testParseNetworks(testConnPtr privconn,
                  const char *file,
                  xmlXPathContextPtr ctxt)
1129 1130 1131 1132 1133 1134 1135
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virNetworkObjPtr obj;

    num = virXPathNodeSet("/node/network", ctxt, &nodes);
1136
    if (num < 0)
1137
        goto error;
1138 1139

    for (i = 0; i < num; i++) {
1140
        virNetworkDefPtr def;
C
Cole Robinson 已提交
1141 1142 1143
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file, "network");
        if (!node)
            goto error;
1144

C
Cole Robinson 已提交
1145 1146 1147
        def = virNetworkDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
1148

1149
        if (!(obj = virNetworkAssignDef(privconn->networks, def, 0))) {
1150 1151
            virNetworkDefFree(def);
            goto error;
1152
        }
1153 1154

        obj->active = 1;
1155
        virNetworkObjEndAPI(&obj);
1156
    }
1157

1158
    ret = 0;
1159
 error:
1160 1161 1162 1163 1164
    VIR_FREE(nodes);
    return ret;
}

static int
C
Cole Robinson 已提交
1165 1166 1167
testParseInterfaces(testConnPtr privconn,
                    const char *file,
                    xmlXPathContextPtr ctxt)
1168 1169 1170 1171 1172 1173 1174
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virInterfaceObjPtr obj;

    num = virXPathNodeSet("/node/interface", ctxt, &nodes);
1175
    if (num < 0)
L
Laine Stump 已提交
1176
        goto error;
1177 1178

    for (i = 0; i < num; i++) {
L
Laine Stump 已提交
1179
        virInterfaceDefPtr def;
C
Cole Robinson 已提交
1180 1181 1182 1183
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "interface");
        if (!node)
            goto error;
L
Laine Stump 已提交
1184

C
Cole Robinson 已提交
1185 1186 1187
        def = virInterfaceDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
1188

1189
        if (!(obj = virInterfaceAssignDef(&privconn->ifaces, def))) {
L
Laine Stump 已提交
1190 1191 1192
            virInterfaceDefFree(def);
            goto error;
        }
1193

1194 1195 1196 1197 1198
        obj->active = 1;
        virInterfaceObjUnlock(obj);
    }

    ret = 0;
1199
 error:
1200 1201 1202 1203 1204
    VIR_FREE(nodes);
    return ret;
}

static int
C
Cole Robinson 已提交
1205
testOpenVolumesForPool(const char *file,
1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221
                       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);
1222
    if (num < 0)
1223 1224 1225
        goto error;

    for (i = 0; i < num; i++) {
C
Cole Robinson 已提交
1226 1227 1228 1229
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "volume");
        if (!node)
            goto error;
1230

1231
        def = virStorageVolDefParseNode(pool->def, ctxt->doc, node, 0);
C
Cole Robinson 已提交
1232 1233
        if (!def)
            goto error;
1234 1235 1236 1237 1238 1239 1240 1241 1242 1243

        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;
1244 1245
        if (VIR_APPEND_ELEMENT_COPY(pool->volumes.objs, pool->volumes.count, def) < 0)
            goto error;
1246

1247
        pool->def->allocation += def->target.allocation;
1248 1249 1250
        pool->def->available = (pool->def->capacity -
                                pool->def->allocation);
        def = NULL;
L
Laine Stump 已提交
1251 1252
    }

1253
    ret = 0;
1254
 error:
1255 1256 1257 1258 1259 1260
    virStorageVolDefFree(def);
    VIR_FREE(nodes);
    return ret;
}

static int
C
Cole Robinson 已提交
1261 1262 1263
testParseStorage(testConnPtr privconn,
                 const char *file,
                 xmlXPathContextPtr ctxt)
1264 1265 1266 1267 1268 1269 1270
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virStoragePoolObjPtr obj;

    num = virXPathNodeSet("/node/pool", ctxt, &nodes);
1271
    if (num < 0)
C
Cole Robinson 已提交
1272
        goto error;
1273 1274

    for (i = 0; i < num; i++) {
C
Cole Robinson 已提交
1275
        virStoragePoolDefPtr def;
C
Cole Robinson 已提交
1276 1277 1278 1279
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "pool");
        if (!node)
            goto error;
C
Cole Robinson 已提交
1280

C
Cole Robinson 已提交
1281 1282 1283
        def = virStoragePoolDefParseNode(ctxt->doc, node);
        if (!def)
            goto error;
C
Cole Robinson 已提交
1284

1285
        if (!(obj = virStoragePoolObjAssignDef(&privconn->pools,
C
Cole Robinson 已提交
1286 1287 1288 1289 1290
                                                def))) {
            virStoragePoolDefFree(def);
            goto error;
        }

1291 1292
        if (testStoragePoolObjSetDefaults(obj) == -1) {
            virStoragePoolObjUnlock(obj);
C
Cole Robinson 已提交
1293
            goto error;
1294
        }
1295
        obj->active = 1;
1296 1297

        /* Find storage volumes */
C
Cole Robinson 已提交
1298
        if (testOpenVolumesForPool(file, ctxt, obj, i+1) < 0) {
1299
            virStoragePoolObjUnlock(obj);
1300 1301 1302
            goto error;
        }

1303
        virStoragePoolObjUnlock(obj);
C
Cole Robinson 已提交
1304 1305
    }

1306
    ret = 0;
1307
 error:
1308 1309 1310 1311 1312
    VIR_FREE(nodes);
    return ret;
}

static int
C
Cole Robinson 已提交
1313 1314 1315
testParseNodedevs(testConnPtr privconn,
                  const char *file,
                  xmlXPathContextPtr ctxt)
1316 1317 1318 1319 1320 1321 1322
{
    int num, ret = -1;
    size_t i;
    xmlNodePtr *nodes = NULL;
    virNodeDeviceObjPtr obj;

    num = virXPathNodeSet("/node/device", ctxt, &nodes);
1323
    if (num < 0)
1324
        goto error;
1325 1326

    for (i = 0; i < num; i++) {
1327
        virNodeDeviceDefPtr def;
C
Cole Robinson 已提交
1328 1329 1330 1331
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                  "nodedev");
        if (!node)
            goto error;
1332

C
Cole Robinson 已提交
1333 1334 1335
        def = virNodeDeviceDefParseNode(ctxt->doc, node, 0, NULL);
        if (!def)
            goto error;
1336 1337

        if (!(obj = virNodeDeviceAssignDef(&privconn->devs, def))) {
1338 1339 1340
            virNodeDeviceDefFree(def);
            goto error;
        }
1341 1342 1343 1344 1345

        virNodeDeviceObjUnlock(obj);
    }

    ret = 0;
1346
 error:
1347 1348 1349 1350
    VIR_FREE(nodes);
    return ret;
}

1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385
static int
testParseAuthUsers(testConnPtr privconn,
                   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;
1386
 error:
1387 1388 1389
    VIR_FREE(nodes);
    return ret;
}
1390 1391 1392

/* No shared state between simultaneous test connections initialized
 * from a file.  */
1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406
static int
testOpenFromFile(virConnectPtr conn, const char *file)
{
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
    testConnPtr privconn;

    if (VIR_ALLOC(privconn) < 0)
        return VIR_DRV_OPEN_ERROR;
    if (virMutexInit(&privconn->lock) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot initialize mutex"));
        VIR_FREE(privconn);
        return VIR_DRV_OPEN_ERROR;
1407 1408
    }

1409 1410 1411
    testDriverLock(privconn);
    conn->privateData = privconn;

1412
    if (!(privconn->domains = virDomainObjListNew()) ||
1413
        !(privconn->networks = virNetworkObjListNew()))
1414 1415 1416 1417 1418 1419 1420 1421
        goto error;

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

    if (!(privconn->xmlopt = testBuildXMLConfig()))
        goto error;

1422
    if (!(privconn->eventState = virObjectEventStateNew()))
1423 1424
        goto error;

1425
    if (!(doc = virXMLParseFileCtxt(file, &ctxt)))
1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441
        goto error;

    if (!xmlStrEqual(ctxt->node->name, BAD_CAST "node")) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("Root element is not 'node'"));
        goto error;
    }

    privconn->nextDomID = 1;
    privconn->numCells = 0;
    if (VIR_STRDUP(privconn->path, file) < 0)
        goto error;
    memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));

    if (testParseNodeInfo(&privconn->nodeInfo, ctxt) < 0)
        goto error;
C
Cole Robinson 已提交
1442
    if (testParseDomains(privconn, file, ctxt) < 0)
1443
        goto error;
C
Cole Robinson 已提交
1444
    if (testParseNetworks(privconn, file, ctxt) < 0)
1445
        goto error;
C
Cole Robinson 已提交
1446
    if (testParseInterfaces(privconn, file, ctxt) < 0)
1447
        goto error;
C
Cole Robinson 已提交
1448
    if (testParseStorage(privconn, file, ctxt) < 0)
1449
        goto error;
C
Cole Robinson 已提交
1450
    if (testParseNodedevs(privconn, file, ctxt) < 0)
1451
        goto error;
1452 1453
    if (testParseAuthUsers(privconn, ctxt) < 0)
        goto error;
1454

J
Jim Meyering 已提交
1455
    xmlXPathFreeContext(ctxt);
1456
    xmlFreeDoc(doc);
1457
    testDriverUnlock(privconn);
1458

1459
    return 0;
1460 1461

 error:
J
Jim Meyering 已提交
1462
    xmlXPathFreeContext(ctxt);
1463
    xmlFreeDoc(doc);
1464
    virObjectUnref(privconn->domains);
1465
    virObjectUnref(privconn->networks);
L
Laine Stump 已提交
1466
    virInterfaceObjListFree(&privconn->ifaces);
C
Cole Robinson 已提交
1467
    virStoragePoolObjListFree(&privconn->pools);
E
Eric Blake 已提交
1468
    VIR_FREE(privconn->path);
1469
    virObjectEventStateFree(privconn->eventState);
1470
    testDriverUnlock(privconn);
1471
    VIR_FREE(privconn);
1472
    conn->privateData = NULL;
1473
    return VIR_DRV_OPEN_ERROR;
1474 1475
}

1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504
static int
testConnectAuthenticate(virConnectPtr conn,
                        virConnectAuthPtr auth)
{
    testConnPtr privconn = conn->privateData;
    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;

1505
 found_user:
1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524
    /* 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;
1525
 cleanup:
1526 1527 1528 1529
    VIR_FREE(username);
    VIR_FREE(password);
    return ret;
}
1530

1531
static virDrvOpenStatus testConnectOpen(virConnectPtr conn,
1532
                                        virConnectAuthPtr auth,
1533
                                        unsigned int flags)
1534
{
1535
    int ret;
1536

E
Eric Blake 已提交
1537 1538
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

1539
    if (!conn->uri)
1540
        return VIR_DRV_OPEN_DECLINED;
1541

1542
    if (!conn->uri->scheme || STRNEQ(conn->uri->scheme, "test"))
1543
        return VIR_DRV_OPEN_DECLINED;
1544

1545
    /* Remote driver should handle these. */
1546
    if (conn->uri->server)
1547 1548
        return VIR_DRV_OPEN_DECLINED;

1549
    /* From this point on, the connection is for us. */
1550 1551 1552
    if (!conn->uri->path
        || conn->uri->path[0] == '\0'
        || (conn->uri->path[0] == '/' && conn->uri->path[1] == '\0')) {
1553 1554
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("testOpen: supply a path or use test:///default"));
1555 1556
        return VIR_DRV_OPEN_ERROR;
    }
1557

1558
    if (STREQ(conn->uri->path, "/default"))
1559 1560
        ret = testOpenDefault(conn);
    else
1561
        ret = testOpenFromFile(conn,
1562
                               conn->uri->path);
1563

1564 1565 1566
    if (ret != VIR_DRV_OPEN_SUCCESS)
        return ret;

1567 1568 1569 1570
    /* Fake authentication. */
    if (testConnectAuthenticate(conn, auth) < 0)
        return VIR_DRV_OPEN_ERROR;

1571
    return VIR_DRV_OPEN_SUCCESS;
1572 1573
}

1574
static int testConnectClose(virConnectPtr conn)
1575
{
1576
    testConnPtr privconn = conn->privateData;
1577 1578 1579 1580 1581 1582 1583 1584 1585

    if (privconn == &defaultConn) {
        virMutexLock(&defaultLock);
        if (--defaultConnections) {
            virMutexUnlock(&defaultLock);
            return 0;
        }
    }

1586
    testDriverLock(privconn);
1587
    virObjectUnref(privconn->caps);
1588
    virObjectUnref(privconn->xmlopt);
1589
    virObjectUnref(privconn->domains);
D
Daniel P. Berrange 已提交
1590
    virNodeDeviceObjListFree(&privconn->devs);
1591
    virObjectUnref(privconn->networks);
L
Laine Stump 已提交
1592
    virInterfaceObjListFree(&privconn->ifaces);
C
Cole Robinson 已提交
1593
    virStoragePoolObjListFree(&privconn->pools);
1594
    virObjectEventStateFree(privconn->eventState);
E
Eric Blake 已提交
1595
    VIR_FREE(privconn->path);
1596

1597
    testDriverUnlock(privconn);
1598
    virMutexDestroy(&privconn->lock);
1599

1600 1601 1602 1603
    if (privconn == &defaultConn)
        virMutexUnlock(&defaultLock);
    else
        VIR_FREE(privconn);
1604
    conn->privateData = NULL;
1605
    return 0;
1606 1607
}

1608 1609
static int testConnectGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
                                 unsigned long *hvVer)
1610
{
1611
    *hvVer = 2;
1612
    return 0;
1613 1614
}

1615 1616 1617 1618 1619 1620
static char *testConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return virGetHostname();
}


1621
static int testConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
1622 1623 1624 1625
{
    return 1;
}

1626
static int testConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
1627 1628 1629 1630
{
    return 0;
}

1631
static int testConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
1632 1633 1634 1635
{
    return 1;
}

1636 1637
static int testConnectGetMaxVcpus(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type ATTRIBUTE_UNUSED)
1638 1639 1640 1641
{
    return 32;
}

1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656
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;
}

1657 1658
static int testNodeGetInfo(virConnectPtr conn,
                           virNodeInfoPtr info)
1659
{
1660
    testConnPtr privconn = conn->privateData;
1661
    testDriverLock(privconn);
1662
    memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo));
1663
    testDriverUnlock(privconn);
1664
    return 0;
1665 1666
}

1667
static char *testConnectGetCapabilities(virConnectPtr conn)
1668
{
1669
    testConnPtr privconn = conn->privateData;
1670
    char *xml;
1671
    testDriverLock(privconn);
1672
    xml = virCapabilitiesFormatXML(privconn->caps);
1673
    testDriverUnlock(privconn);
1674
    return xml;
1675 1676
}

1677
static int testConnectNumOfDomains(virConnectPtr conn)
1678
{
1679
    testConnPtr privconn = conn->privateData;
1680
    int count;
1681

1682
    testDriverLock(privconn);
1683
    count = virDomainObjListNumOfDomains(privconn->domains, true, NULL, NULL);
1684
    testDriverUnlock(privconn);
1685

1686
    return count;
1687 1688
}

1689 1690 1691 1692 1693 1694 1695
static int testDomainIsActive(virDomainPtr dom)
{
    testConnPtr privconn = dom->conn->privateData;
    virDomainObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
1696
    obj = virDomainObjListFindByUUID(privconn->domains, dom->uuid);
1697 1698
    testDriverUnlock(privconn);
    if (!obj) {
1699
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1700 1701 1702 1703
        goto cleanup;
    }
    ret = virDomainObjIsActive(obj);

1704
 cleanup:
1705
    if (obj)
1706
        virObjectUnlock(obj);
1707 1708 1709 1710 1711 1712 1713 1714 1715 1716
    return ret;
}

static int testDomainIsPersistent(virDomainPtr dom)
{
    testConnPtr privconn = dom->conn->privateData;
    virDomainObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
1717
    obj = virDomainObjListFindByUUID(privconn->domains, dom->uuid);
1718 1719
    testDriverUnlock(privconn);
    if (!obj) {
1720
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1721 1722 1723 1724
        goto cleanup;
    }
    ret = obj->persistent;

1725
 cleanup:
1726
    if (obj)
1727
        virObjectUnlock(obj);
1728 1729 1730
    return ret;
}

1731 1732 1733 1734 1735
static int testDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
{
    return 0;
}

1736
static virDomainPtr
1737
testDomainCreateXML(virConnectPtr conn, const char *xml,
1738
                      unsigned int flags)
1739
{
1740
    testConnPtr privconn = conn->privateData;
1741
    virDomainPtr ret = NULL;
1742
    virDomainDefPtr def;
1743
    virDomainObjPtr dom = NULL;
1744
    virObjectEventPtr event = NULL;
1745
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
1746

1747 1748 1749 1750
    virCheckFlags(VIR_DOMAIN_START_VALIDATE, NULL);

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

1752
    testDriverLock(privconn);
1753
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
1754
                                       parse_flags)) == NULL)
1755
        goto cleanup;
1756

1757
    if (testDomainGenerateIfnames(def) < 0)
1758
        goto cleanup;
1759
    if (!(dom = virDomainObjListAdd(privconn->domains,
1760
                                    def,
1761
                                    privconn->xmlopt,
1762 1763
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
1764 1765
        goto cleanup;
    def = NULL;
1766

1767
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_BOOTED) < 0)
1768
        goto cleanup;
1769

1770
    event = virDomainEventLifecycleNewFromObj(dom,
1771 1772 1773
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);

1774
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1775
    if (ret)
1776
        ret->id = dom->def->id;
1777

1778
 cleanup:
1779
    if (dom)
1780
        virObjectUnlock(dom);
1781
    if (event)
1782
        testObjectEventQueue(privconn, event);
1783
    virDomainDefFree(def);
1784
    testDriverUnlock(privconn);
1785
    return ret;
1786 1787 1788
}


1789
static virDomainPtr testDomainLookupByID(virConnectPtr conn,
1790
                                         int id)
1791
{
1792
    testConnPtr privconn = conn->privateData;
1793 1794
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1795

1796
    testDriverLock(privconn);
1797
    dom = virDomainObjListFindByID(privconn->domains, id);
1798 1799 1800
    testDriverUnlock(privconn);

    if (dom == NULL) {
1801
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1802
        goto cleanup;
1803 1804
    }

1805
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1806 1807 1808
    if (ret)
        ret->id = dom->def->id;

1809
 cleanup:
1810
    if (dom)
1811
        virObjectUnlock(dom);
1812
    return ret;
1813 1814
}

1815
static virDomainPtr testDomainLookupByUUID(virConnectPtr conn,
1816
                                           const unsigned char *uuid)
1817
{
1818
    testConnPtr privconn = conn->privateData;
1819
    virDomainPtr ret = NULL;
1820
    virDomainObjPtr dom;
1821

1822
    testDriverLock(privconn);
1823
    dom = virDomainObjListFindByUUID(privconn->domains, uuid);
1824 1825 1826
    testDriverUnlock(privconn);

    if (dom == NULL) {
1827
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1828
        goto cleanup;
1829
    }
1830

1831
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1832 1833 1834
    if (ret)
        ret->id = dom->def->id;

1835
 cleanup:
1836
    if (dom)
1837
        virObjectUnlock(dom);
1838
    return ret;
1839 1840
}

1841
static virDomainPtr testDomainLookupByName(virConnectPtr conn,
1842
                                           const char *name)
1843
{
1844
    testConnPtr privconn = conn->privateData;
1845 1846
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1847

1848
    testDriverLock(privconn);
1849
    dom = virDomainObjListFindByName(privconn->domains, name);
1850 1851 1852
    testDriverUnlock(privconn);

    if (dom == NULL) {
1853
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1854
        goto cleanup;
1855
    }
1856

1857
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1858 1859 1860
    if (ret)
        ret->id = dom->def->id;

1861
 cleanup:
1862
    virDomainObjEndAPI(&dom);
1863
    return ret;
1864 1865
}

1866 1867 1868
static int testConnectListDomains(virConnectPtr conn,
                                  int *ids,
                                  int maxids)
1869
{
1870
    testConnPtr privconn = conn->privateData;
1871
    int n;
1872

1873
    testDriverLock(privconn);
1874
    n = virDomainObjListGetActiveIDs(privconn->domains, ids, maxids, NULL, NULL);
1875
    testDriverUnlock(privconn);
1876

1877
    return n;
1878 1879
}

1880
static int testDomainDestroy(virDomainPtr domain)
1881
{
1882 1883
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1884
    virObjectEventPtr event = NULL;
1885
    int ret = -1;
1886

1887
    testDriverLock(privconn);
1888 1889
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1890 1891

    if (privdom == NULL) {
1892
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1893
        goto cleanup;
1894
    }
1895

J
Jiri Denemark 已提交
1896
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_DESTROYED);
1897
    event = virDomainEventLifecycleNewFromObj(privdom,
1898 1899
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
1900

1901 1902
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
1903 1904

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

1913
static int testDomainResume(virDomainPtr domain)
1914
{
1915 1916
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1917
    virObjectEventPtr event = NULL;
1918
    int ret = -1;
1919

1920
    testDriverLock(privconn);
1921 1922
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1923
    testDriverUnlock(privconn);
1924 1925

    if (privdom == NULL) {
1926
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1927
        goto cleanup;
1928
    }
1929

J
Jiri Denemark 已提交
1930
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_PAUSED) {
1931 1932
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"),
                       domain->name);
1933
        goto cleanup;
1934
    }
1935

J
Jiri Denemark 已提交
1936 1937
    virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                         VIR_DOMAIN_RUNNING_UNPAUSED);
1938
    event = virDomainEventLifecycleNewFromObj(privdom,
1939 1940
                                     VIR_DOMAIN_EVENT_RESUMED,
                                     VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
1941 1942
    ret = 0;

1943
 cleanup:
1944
    virDomainObjEndAPI(&privdom);
1945 1946
    if (event) {
        testDriverLock(privconn);
1947
        testObjectEventQueue(privconn, event);
1948 1949
        testDriverUnlock(privconn);
    }
1950
    return ret;
1951 1952
}

1953
static int testDomainSuspend(virDomainPtr domain)
1954
{
1955 1956
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1957
    virObjectEventPtr event = NULL;
1958
    int ret = -1;
J
Jiri Denemark 已提交
1959
    int state;
1960

1961
    testDriverLock(privconn);
1962 1963
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
1964
    testDriverUnlock(privconn);
1965 1966

    if (privdom == NULL) {
1967
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1968
        goto cleanup;
1969
    }
1970

J
Jiri Denemark 已提交
1971 1972
    state = virDomainObjGetState(privdom, NULL);
    if (state == VIR_DOMAIN_SHUTOFF || state == VIR_DOMAIN_PAUSED) {
1973 1974
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"),
                       domain->name);
1975
        goto cleanup;
1976
    }
1977

J
Jiri Denemark 已提交
1978
    virDomainObjSetState(privdom, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
1979
    event = virDomainEventLifecycleNewFromObj(privdom,
1980 1981
                                     VIR_DOMAIN_EVENT_SUSPENDED,
                                     VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
1982 1983
    ret = 0;

1984
 cleanup:
1985
    virDomainObjEndAPI(&privdom);
1986 1987 1988

    if (event) {
        testDriverLock(privconn);
1989
        testObjectEventQueue(privconn, event);
1990 1991
        testDriverUnlock(privconn);
    }
1992
    return ret;
1993 1994
}

1995
static int testDomainShutdownFlags(virDomainPtr domain,
1996
                                   unsigned int flags)
1997
{
1998 1999
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2000
    virObjectEventPtr event = NULL;
2001
    int ret = -1;
2002

2003 2004
    virCheckFlags(0, -1);

2005
    testDriverLock(privconn);
2006 2007
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2008 2009

    if (privdom == NULL) {
2010
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2011
        goto cleanup;
2012
    }
2013

J
Jiri Denemark 已提交
2014
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
2015 2016
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("domain '%s' not running"), domain->name);
2017
        goto cleanup;
2018
    }
2019

J
Jiri Denemark 已提交
2020
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
2021
    event = virDomainEventLifecycleNewFromObj(privdom,
2022 2023
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
2024

2025 2026
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
2027

2028
    ret = 0;
2029
 cleanup:
2030
    virDomainObjEndAPI(&privdom);
2031
    if (event)
2032
        testObjectEventQueue(privconn, event);
2033
    testDriverUnlock(privconn);
2034
    return ret;
2035 2036
}

2037
static int testDomainShutdown(virDomainPtr domain)
2038
{
2039
    return testDomainShutdownFlags(domain, 0);
2040 2041
}

2042
/* Similar behaviour as shutdown */
2043
static int testDomainReboot(virDomainPtr domain,
2044
                            unsigned int action ATTRIBUTE_UNUSED)
2045
{
2046 2047
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2048
    virObjectEventPtr event = NULL;
2049
    int ret = -1;
2050

2051
    testDriverLock(privconn);
2052 2053
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2054 2055

    if (privdom == NULL) {
2056
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2057
        goto cleanup;
2058
    }
2059

J
Jiri Denemark 已提交
2060 2061 2062
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTDOWN,
                         VIR_DOMAIN_SHUTDOWN_USER);

2063 2064
    switch (privdom->def->onReboot) {
    case VIR_DOMAIN_LIFECYCLE_DESTROY:
J
Jiri Denemark 已提交
2065 2066
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
2067 2068
        break;

2069
    case VIR_DOMAIN_LIFECYCLE_RESTART:
J
Jiri Denemark 已提交
2070 2071
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
2072 2073
        break;

2074
    case VIR_DOMAIN_LIFECYCLE_PRESERVE:
J
Jiri Denemark 已提交
2075 2076
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
2077 2078
        break;

2079
    case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME:
J
Jiri Denemark 已提交
2080 2081
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
2082
        break;
2083

2084
    default:
J
Jiri Denemark 已提交
2085 2086
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
2087 2088
        break;
    }
2089

J
Jiri Denemark 已提交
2090 2091
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
2092
        event = virDomainEventLifecycleNewFromObj(privdom,
2093 2094
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
2095

2096 2097
        if (!privdom->persistent)
            virDomainObjListRemove(privconn->domains, privdom);
2098 2099
    }

2100
    ret = 0;
2101
 cleanup:
2102
    virDomainObjEndAPI(&privdom);
2103
    if (event)
2104
        testObjectEventQueue(privconn, event);
2105
    testDriverUnlock(privconn);
2106
    return ret;
2107 2108
}

2109
static int testDomainGetInfo(virDomainPtr domain,
2110
                             virDomainInfoPtr info)
2111
{
2112
    testConnPtr privconn = domain->conn->privateData;
2113
    struct timeval tv;
2114
    virDomainObjPtr privdom;
2115
    int ret = -1;
2116

2117
    testDriverLock(privconn);
2118 2119
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2120
    testDriverUnlock(privconn);
2121 2122

    if (privdom == NULL) {
2123
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2124
        goto cleanup;
2125
    }
2126 2127

    if (gettimeofday(&tv, NULL) < 0) {
2128 2129
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("getting time of day"));
2130
        goto cleanup;
2131 2132
    }

J
Jiri Denemark 已提交
2133
    info->state = virDomainObjGetState(privdom, NULL);
2134
    info->memory = privdom->def->mem.cur_balloon;
2135
    info->maxMem = virDomainDefGetMemoryActual(privdom->def);
2136 2137
    info->nrVirtCpu = privdom->def->vcpus;
    info->cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
2138 2139
    ret = 0;

2140
 cleanup:
2141
    virDomainObjEndAPI(&privdom);
2142
    return ret;
2143 2144
}

2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157
static int
testDomainGetState(virDomainPtr domain,
                   int *state,
                   int *reason,
                   unsigned int flags)
{
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
    int ret = -1;

    virCheckFlags(0, -1);

    testDriverLock(privconn);
2158 2159
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2160 2161 2162
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2163
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2164 2165 2166
        goto cleanup;
    }

J
Jiri Denemark 已提交
2167
    *state = virDomainObjGetState(privdom, reason);
2168 2169
    ret = 0;

2170
 cleanup:
2171
    virDomainObjEndAPI(&privdom);
2172 2173 2174
    return ret;
}

2175 2176
#define TEST_SAVE_MAGIC "TestGuestMagic"

2177 2178 2179
static int
testDomainSaveFlags(virDomainPtr domain, const char *path,
                    const char *dxml, unsigned int flags)
2180
{
2181
    testConnPtr privconn = domain->conn->privateData;
2182 2183 2184
    char *xml = NULL;
    int fd = -1;
    int len;
2185
    virDomainObjPtr privdom;
2186
    virObjectEventPtr event = NULL;
2187
    int ret = -1;
2188

2189 2190
    virCheckFlags(0, -1);
    if (dxml) {
2191 2192
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
2193 2194 2195
        return -1;
    }

2196
    testDriverLock(privconn);
2197 2198
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2199 2200

    if (privdom == NULL) {
2201
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2202
        goto cleanup;
2203
    }
2204

2205
    xml = virDomainDefFormat(privdom->def,
2206
                             VIR_DOMAIN_DEF_FORMAT_SECURE);
C
Cole Robinson 已提交
2207

2208
    if (xml == NULL) {
2209
        virReportSystemError(errno,
2210 2211
                             _("saving domain '%s' failed to allocate space for metadata"),
                             domain->name);
2212
        goto cleanup;
2213
    }
2214 2215

    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
2216
        virReportSystemError(errno,
2217 2218
                             _("saving domain '%s' to '%s': open failed"),
                             domain->name, path);
2219
        goto cleanup;
2220
    }
2221
    len = strlen(xml);
2222
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
2223
        virReportSystemError(errno,
2224 2225
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
2226
        goto cleanup;
2227
    }
2228
    if (safewrite(fd, (char*)&len, sizeof(len)) < 0) {
2229
        virReportSystemError(errno,
2230 2231
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
2232
        goto cleanup;
2233
    }
2234
    if (safewrite(fd, xml, len) < 0) {
2235
        virReportSystemError(errno,
2236 2237
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
2238
        goto cleanup;
2239
    }
2240

2241
    if (VIR_CLOSE(fd) < 0) {
2242
        virReportSystemError(errno,
2243 2244
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
2245
        goto cleanup;
2246
    }
2247 2248
    fd = -1;

J
Jiri Denemark 已提交
2249
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SAVED);
2250
    event = virDomainEventLifecycleNewFromObj(privdom,
2251 2252
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
2253

2254 2255
    if (!privdom->persistent)
        virDomainObjListRemove(privconn->domains, privdom);
2256

2257
    ret = 0;
2258
 cleanup:
2259 2260 2261 2262 2263 2264
    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) {
2265
        VIR_FORCE_CLOSE(fd);
2266 2267
        unlink(path);
    }
2268
    virDomainObjEndAPI(&privdom);
2269
    if (event)
2270
        testObjectEventQueue(privconn, event);
2271
    testDriverUnlock(privconn);
2272
    return ret;
2273 2274
}

2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286
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)
2287
{
2288
    testConnPtr privconn = conn->privateData;
2289
    char *xml = NULL;
2290
    char magic[15];
2291 2292 2293
    int fd = -1;
    int len;
    virDomainDefPtr def = NULL;
2294
    virDomainObjPtr dom = NULL;
2295
    virObjectEventPtr event = NULL;
2296
    int ret = -1;
2297

2298 2299
    virCheckFlags(0, -1);
    if (dxml) {
2300 2301
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
2302 2303 2304
        return -1;
    }

2305 2306
    testDriverLock(privconn);

2307
    if ((fd = open(path, O_RDONLY)) < 0) {
2308
        virReportSystemError(errno,
2309 2310
                             _("cannot read domain image '%s'"),
                             path);
2311
        goto cleanup;
2312
    }
2313
    if (saferead(fd, magic, sizeof(magic)) != sizeof(magic)) {
2314
        virReportSystemError(errno,
2315 2316
                             _("incomplete save header in '%s'"),
                             path);
2317
        goto cleanup;
2318
    }
2319
    if (memcmp(magic, TEST_SAVE_MAGIC, sizeof(magic))) {
2320 2321
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("mismatched header magic"));
2322
        goto cleanup;
2323
    }
2324
    if (saferead(fd, (char*)&len, sizeof(len)) != sizeof(len)) {
2325
        virReportSystemError(errno,
2326 2327
                             _("failed to read metadata length in '%s'"),
                             path);
2328
        goto cleanup;
2329 2330
    }
    if (len < 1 || len > 8192) {
2331 2332
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("length of metadata out of range"));
2333
        goto cleanup;
2334
    }
2335
    if (VIR_ALLOC_N(xml, len+1) < 0)
2336
        goto cleanup;
2337
    if (saferead(fd, xml, len) != len) {
2338
        virReportSystemError(errno,
2339
                             _("incomplete metadata in '%s'"), path);
2340
        goto cleanup;
2341 2342
    }
    xml[len] = '\0';
2343

2344
    def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
2345
                                  VIR_DOMAIN_DEF_PARSE_INACTIVE);
2346
    if (!def)
2347
        goto cleanup;
2348

2349
    if (testDomainGenerateIfnames(def) < 0)
2350
        goto cleanup;
2351
    if (!(dom = virDomainObjListAdd(privconn->domains,
2352
                                    def,
2353
                                    privconn->xmlopt,
2354 2355 2356
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
2357 2358
        goto cleanup;
    def = NULL;
2359

2360
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_RESTORED) < 0)
2361 2362
        goto cleanup;

2363
    event = virDomainEventLifecycleNewFromObj(dom,
2364 2365
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
2366
    ret = 0;
2367

2368
 cleanup:
2369 2370
    virDomainDefFree(def);
    VIR_FREE(xml);
2371
    VIR_FORCE_CLOSE(fd);
2372
    if (dom)
2373
        virObjectUnlock(dom);
2374
    if (event)
2375
        testObjectEventQueue(privconn, event);
2376
    testDriverUnlock(privconn);
2377
    return ret;
2378 2379
}

2380 2381 2382 2383 2384 2385 2386
static int
testDomainRestore(virConnectPtr conn,
                  const char *path)
{
    return testDomainRestoreFlags(conn, path, NULL, 0);
}

2387 2388 2389 2390
static int testDomainCoreDumpWithFormat(virDomainPtr domain,
                                        const char *to,
                                        unsigned int dumpformat,
                                        unsigned int flags)
2391
{
2392
    testConnPtr privconn = domain->conn->privateData;
2393
    int fd = -1;
2394
    virDomainObjPtr privdom;
2395
    virObjectEventPtr event = NULL;
2396
    int ret = -1;
2397

E
Eric Blake 已提交
2398 2399
    virCheckFlags(VIR_DUMP_CRASH, -1);

2400
    testDriverLock(privconn);
2401 2402
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2403 2404

    if (privdom == NULL) {
2405
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2406
        goto cleanup;
2407
    }
2408 2409

    if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
2410
        virReportSystemError(errno,
2411 2412
                             _("domain '%s' coredump: failed to open %s"),
                             domain->name, to);
2413
        goto cleanup;
2414
    }
2415
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
2416
        virReportSystemError(errno,
2417 2418
                             _("domain '%s' coredump: failed to write header to %s"),
                             domain->name, to);
2419
        goto cleanup;
2420
    }
2421
    if (VIR_CLOSE(fd) < 0) {
2422
        virReportSystemError(errno,
2423 2424
                             _("domain '%s' coredump: write failed: %s"),
                             domain->name, to);
2425
        goto cleanup;
2426
    }
2427

2428 2429 2430 2431 2432 2433 2434
    /* 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;
    }

2435
    if (flags & VIR_DUMP_CRASH) {
J
Jiri Denemark 已提交
2436
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_CRASHED);
2437
        event = virDomainEventLifecycleNewFromObj(privdom,
2438 2439
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
2440 2441
        if (!privdom->persistent)
            virDomainObjListRemove(privconn->domains, privdom);
2442
    }
2443

2444
    ret = 0;
2445
 cleanup:
2446
    VIR_FORCE_CLOSE(fd);
2447
    virDomainObjEndAPI(&privdom);
2448
    if (event)
2449
        testObjectEventQueue(privconn, event);
2450
    testDriverUnlock(privconn);
2451
    return ret;
2452 2453
}

2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467

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)
{
2468 2469 2470
    char *ret;

    ignore_value(VIR_STRDUP(ret, "linux"));
2471
    return ret;
2472 2473
}

2474 2475 2476

static unsigned long long
testDomainGetMaxMemory(virDomainPtr domain)
2477
{
2478 2479
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2480
    unsigned long long ret = 0;
2481

2482
    testDriverLock(privconn);
2483 2484
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2485
    testDriverUnlock(privconn);
2486 2487

    if (privdom == NULL) {
2488
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2489
        goto cleanup;
2490
    }
2491

2492
    ret = virDomainDefGetMemoryActual(privdom->def);
2493

2494
 cleanup:
2495
    virDomainObjEndAPI(&privdom);
2496
    return ret;
2497 2498
}

2499 2500
static int testDomainSetMaxMemory(virDomainPtr domain,
                                  unsigned long memory)
2501
{
2502 2503
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2504
    int ret = -1;
2505

2506
    testDriverLock(privconn);
2507 2508
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2509
    testDriverUnlock(privconn);
2510 2511

    if (privdom == NULL) {
2512
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2513
        goto cleanup;
2514
    }
2515 2516

    /* XXX validate not over host memory wrt to other domains */
2517
    virDomainDefSetMemoryInitial(privdom->def, memory);
2518 2519
    ret = 0;

2520
 cleanup:
2521
    virDomainObjEndAPI(&privdom);
2522
    return ret;
2523 2524
}

2525 2526
static int testDomainSetMemory(virDomainPtr domain,
                               unsigned long memory)
2527
{
2528 2529
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2530
    int ret = -1;
2531

2532
    testDriverLock(privconn);
2533 2534
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2535
    testDriverUnlock(privconn);
2536 2537

    if (privdom == NULL) {
2538
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2539
        goto cleanup;
2540
    }
2541

2542
    if (memory > virDomainDefGetMemoryActual(privdom->def)) {
2543
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2544
        goto cleanup;
2545
    }
2546

2547
    privdom->def->mem.cur_balloon = memory;
2548 2549
    ret = 0;

2550
 cleanup:
2551
    virDomainObjEndAPI(&privdom);
2552
    return ret;
2553 2554
}

2555 2556
static int
testDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
C
Cole Robinson 已提交
2557
{
2558 2559 2560 2561 2562
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr vm;
    virDomainDefPtr def;
    int ret = -1;

2563 2564
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2565 2566 2567
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

    testDriverLock(privconn);
2568
    vm = virDomainObjListFindByUUID(privconn->domains, domain->uuid);
2569 2570 2571 2572 2573
    testDriverUnlock(privconn);

    if (!vm) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(domain->uuid, uuidstr);
2574 2575
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching uuid '%s'"), uuidstr);
2576 2577 2578
        goto cleanup;
    }

2579
    if (virDomainLiveConfigHelperMethod(privconn->caps, privconn->xmlopt,
2580
                                        vm, &flags, &def) < 0)
2581
        goto cleanup;
2582

2583
    if (flags & VIR_DOMAIN_AFFECT_LIVE)
2584 2585 2586 2587
        def = vm->def;

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

2588
 cleanup:
2589
    if (vm)
2590
        virObjectUnlock(vm);
2591
    return ret;
C
Cole Robinson 已提交
2592 2593
}

2594 2595 2596
static int
testDomainGetMaxVcpus(virDomainPtr domain)
{
2597
    return testDomainGetVcpusFlags(domain, (VIR_DOMAIN_AFFECT_LIVE |
2598 2599 2600 2601 2602 2603 2604
                                            VIR_DOMAIN_VCPU_MAXIMUM));
}

static int
testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
                        unsigned int flags)
{
2605
    testConnPtr privconn = domain->conn->privateData;
2606
    virDomainObjPtr privdom = NULL;
2607
    virDomainDefPtr persistentDef;
C
Cole Robinson 已提交
2608 2609
    int ret = -1, maxvcpus;

2610 2611
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2612 2613 2614 2615
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

    /* At least one of LIVE or CONFIG must be set.  MAXIMUM cannot be
     * mixed with LIVE.  */
2616 2617 2618
    if ((flags & (VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG)) == 0 ||
        (flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_AFFECT_LIVE)) ==
         (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_AFFECT_LIVE)) {
2619 2620
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
2621 2622
        return -1;
    }
2623
    if (!nrCpus || (maxvcpus = testConnectGetMaxVcpus(domain->conn, NULL)) < nrCpus) {
2624 2625
        virReportError(VIR_ERR_INVALID_ARG,
                       _("argument out of range: %d"), nrCpus);
2626 2627
        return -1;
    }
2628

2629
    testDriverLock(privconn);
2630
    privdom = virDomainObjListFindByUUID(privconn->domains, domain->uuid);
2631 2632 2633
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2634
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2635
        goto cleanup;
2636
    }
2637

2638
    if (!virDomainObjIsActive(privdom) && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
2639 2640
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot hotplug vcpus for an inactive domain"));
C
Cole Robinson 已提交
2641 2642 2643
        goto cleanup;
    }

2644 2645
    /* We allow more cpus in guest than host, but not more than the
     * domain's starting limit.  */
C
Cole Robinson 已提交
2646 2647
    if (!(flags & (VIR_DOMAIN_VCPU_MAXIMUM)) &&
        privdom->def->maxvcpus < maxvcpus)
2648
        maxvcpus = privdom->def->maxvcpus;
C
Cole Robinson 已提交
2649

C
Cole Robinson 已提交
2650
    if (nrCpus > maxvcpus) {
2651 2652 2653
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested cpu amount exceeds maximum (%d > %d)"),
                       nrCpus, maxvcpus);
2654
        goto cleanup;
2655
    }
2656

2657
    if (!(persistentDef = virDomainObjGetPersistentDef(privconn->caps,
2658
                                                       privconn->xmlopt,
2659 2660 2661
                                                       privdom)))
        goto cleanup;

2662
    switch (flags) {
2663
    case VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_AFFECT_CONFIG:
2664 2665 2666
        persistentDef->maxvcpus = nrCpus;
        if (nrCpus < persistentDef->vcpus)
            persistentDef->vcpus = nrCpus;
2667 2668
        ret = 0;
        break;
2669

2670
    case VIR_DOMAIN_AFFECT_CONFIG:
2671
        persistentDef->vcpus = nrCpus;
2672 2673 2674
        ret = 0;
        break;

2675
    case VIR_DOMAIN_AFFECT_LIVE:
2676
        ret = testDomainUpdateVCPUs(privconn, privdom, nrCpus, 0);
2677 2678
        break;

2679
    case VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG:
2680
        ret = testDomainUpdateVCPUs(privconn, privdom, nrCpus, 0);
2681
        if (ret == 0)
2682
            persistentDef->vcpus = nrCpus;
2683 2684
        break;
    }
2685

2686
 cleanup:
2687
    if (privdom)
2688
        virObjectUnlock(privdom);
2689
    return ret;
2690 2691
}

2692
static int
2693
testDomainSetVcpus(virDomainPtr domain, unsigned int nrCpus)
2694
{
2695
    return testDomainSetVcpusFlags(domain, nrCpus, VIR_DOMAIN_AFFECT_LIVE);
2696 2697
}

C
Cole Robinson 已提交
2698 2699 2700 2701 2702 2703 2704 2705 2706
static int testDomainGetVcpus(virDomainPtr domain,
                              virVcpuInfoPtr info,
                              int maxinfo,
                              unsigned char *cpumaps,
                              int maplen)
{
    testConnPtr privconn = domain->conn->privateData;
    testDomainObjPrivatePtr privdomdata;
    virDomainObjPtr privdom;
2707 2708
    size_t i;
    int v, maxcpu, hostcpus;
C
Cole Robinson 已提交
2709 2710 2711 2712 2713
    int ret = -1;
    struct timeval tv;
    unsigned long long statbase;

    testDriverLock(privconn);
2714
    privdom = virDomainObjListFindByName(privconn->domains, domain->name);
C
Cole Robinson 已提交
2715 2716 2717
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2718
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
C
Cole Robinson 已提交
2719 2720 2721 2722
        goto cleanup;
    }

    if (!virDomainObjIsActive(privdom)) {
2723
        virReportError(VIR_ERR_OPERATION_INVALID,
2724
                       "%s", _("cannot list vcpus for an inactive domain"));
C
Cole Robinson 已提交
2725 2726 2727 2728 2729 2730
        goto cleanup;
    }

    privdomdata = privdom->privateData;

    if (gettimeofday(&tv, NULL) < 0) {
2731
        virReportSystemError(errno,
C
Cole Robinson 已提交
2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751
                             "%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;

    /* Clamp to actual number of vcpus */
    if (maxinfo > privdom->def->vcpus)
        maxinfo = privdom->def->vcpus;

    /* Populate virVcpuInfo structures */
    if (info != NULL) {
        memset(info, 0, sizeof(*info) * maxinfo);

2752
        for (i = 0; i < maxinfo; i++) {
C
Cole Robinson 已提交
2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768
            virVcpuInfo privinfo = privdomdata->vcpu_infos[i];

            info[i].number = privinfo.number;
            info[i].state = privinfo.state;
            info[i].cpu = privinfo.cpu;

            /* Fake an increasing cpu time value */
            info[i].cpuTime = statbase / 10;
        }
    }

    /* Populate cpumaps */
    if (cpumaps != NULL) {
        int privmaplen = VIR_CPU_MAPLEN(hostcpus);
        memset(cpumaps, 0, maplen * maxinfo);

2769
        for (v = 0; v < maxinfo; v++) {
C
Cole Robinson 已提交
2770 2771
            unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v);

2772
            for (i = 0; i < maxcpu; i++) {
2773
                if (VIR_CPU_USABLE(privdomdata->cpumaps, privmaplen, v, i))
C
Cole Robinson 已提交
2774 2775 2776 2777 2778 2779
                    VIR_USE_CPU(cpumap, i);
            }
        }
    }

    ret = maxinfo;
2780
 cleanup:
2781
    virDomainObjEndAPI(&privdom);
C
Cole Robinson 已提交
2782 2783 2784
    return ret;
}

C
Cole Robinson 已提交
2785 2786 2787 2788 2789 2790 2791 2792 2793
static int testDomainPinVcpu(virDomainPtr domain,
                             unsigned int vcpu,
                             unsigned char *cpumap,
                             int maplen)
{
    testConnPtr privconn = domain->conn->privateData;
    testDomainObjPrivatePtr privdomdata;
    virDomainObjPtr privdom;
    unsigned char *privcpumap;
2794 2795
    size_t i;
    int maxcpu, hostcpus, privmaplen;
C
Cole Robinson 已提交
2796 2797 2798
    int ret = -1;

    testDriverLock(privconn);
2799
    privdom = virDomainObjListFindByName(privconn->domains, domain->name);
C
Cole Robinson 已提交
2800 2801 2802
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2803
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
C
Cole Robinson 已提交
2804 2805 2806 2807
        goto cleanup;
    }

    if (!virDomainObjIsActive(privdom)) {
2808
        virReportError(VIR_ERR_OPERATION_INVALID,
2809
                       "%s", _("cannot pin vcpus on an inactive domain"));
C
Cole Robinson 已提交
2810 2811 2812 2813
        goto cleanup;
    }

    if (vcpu > privdom->def->vcpus) {
2814 2815
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("requested vcpu is higher than allocated vcpus"));
C
Cole Robinson 已提交
2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829
        goto cleanup;
    }

    privdomdata = privdom->privateData;
    hostcpus = VIR_NODEINFO_MAXCPUS(privconn->nodeInfo);
    privmaplen = VIR_CPU_MAPLEN(hostcpus);

    maxcpu = maplen * 8;
    if (maxcpu > hostcpus)
        maxcpu = hostcpus;

    privcpumap = VIR_GET_CPUMAP(privdomdata->cpumaps, privmaplen, vcpu);
    memset(privcpumap, 0, privmaplen);

2830
    for (i = 0; i < maxcpu; i++) {
2831
        if (VIR_CPU_USABLE(cpumap, maplen, 0, i))
C
Cole Robinson 已提交
2832 2833 2834 2835
            VIR_USE_CPU(privcpumap, i);
    }

    ret = 0;
2836
 cleanup:
2837
    virDomainObjEndAPI(&privdom);
C
Cole Robinson 已提交
2838 2839 2840
    return ret;
}

2841
static char *testDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
2842
{
2843
    testConnPtr privconn = domain->conn->privateData;
2844
    virDomainDefPtr def;
2845
    virDomainObjPtr privdom;
2846 2847
    char *ret = NULL;

2848 2849
    /* Flags checked by virDomainDefFormat */

2850
    testDriverLock(privconn);
2851 2852
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
2853 2854 2855
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2856
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2857
        goto cleanup;
2858
    }
2859

2860 2861
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
2862

2863
    ret = virDomainDefFormat(def,
2864
                             virDomainDefFormatConvertXMLFlags(flags));
2865

2866
 cleanup:
2867
    virDomainObjEndAPI(&privdom);
2868
    return ret;
2869
}
2870

2871 2872
static int testConnectNumOfDefinedDomains(virConnectPtr conn)
{
2873
    testConnPtr privconn = conn->privateData;
2874
    int count;
2875

2876
    testDriverLock(privconn);
2877
    count = virDomainObjListNumOfDomains(privconn->domains, false, NULL, NULL);
2878
    testDriverUnlock(privconn);
2879

2880
    return count;
2881 2882
}

2883 2884
static int testConnectListDefinedDomains(virConnectPtr conn,
                                         char **const names,
2885 2886
                                         int maxnames)
{
2887

2888
    testConnPtr privconn = conn->privateData;
2889
    int n;
2890

2891
    testDriverLock(privconn);
2892
    memset(names, 0, sizeof(*names)*maxnames);
2893 2894
    n = virDomainObjListGetInactiveNames(privconn->domains, names, maxnames,
                                         NULL, NULL);
2895
    testDriverUnlock(privconn);
2896

2897
    return n;
2898 2899
}

2900 2901 2902
static virDomainPtr testDomainDefineXMLFlags(virConnectPtr conn,
                                             const char *xml,
                                             unsigned int flags)
2903
{
2904
    testConnPtr privconn = conn->privateData;
2905
    virDomainPtr ret = NULL;
2906
    virDomainDefPtr def;
2907
    virDomainObjPtr dom = NULL;
2908
    virObjectEventPtr event = NULL;
2909
    virDomainDefPtr oldDef = NULL;
2910 2911 2912
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;

    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
2913

2914 2915
    if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE;
2916

2917
    testDriverLock(privconn);
2918
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
2919
                                       parse_flags)) == NULL)
2920
        goto cleanup;
2921

2922
    if (testDomainGenerateIfnames(def) < 0)
2923
        goto cleanup;
2924
    if (!(dom = virDomainObjListAdd(privconn->domains,
2925
                                    def,
2926
                                    privconn->xmlopt,
2927 2928
                                    0,
                                    &oldDef)))
2929
        goto cleanup;
2930
    def = NULL;
2931
    dom->persistent = 1;
2932

2933
    event = virDomainEventLifecycleNewFromObj(dom,
2934
                                     VIR_DOMAIN_EVENT_DEFINED,
2935
                                     !oldDef ?
2936 2937
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
2938

2939
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
2940
    if (ret)
2941
        ret->id = dom->def->id;
2942

2943
 cleanup:
2944
    virDomainDefFree(def);
2945
    virDomainDefFree(oldDef);
2946
    if (dom)
2947
        virObjectUnlock(dom);
2948
    if (event)
2949
        testObjectEventQueue(privconn, event);
2950
    testDriverUnlock(privconn);
2951
    return ret;
2952 2953
}

2954 2955 2956 2957 2958 2959
static virDomainPtr
testDomainDefineXML(virConnectPtr conn, const char *xml)
{
    return testDomainDefineXMLFlags(conn, xml, 0);
}

2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984
static char *testDomainGetMetadata(virDomainPtr dom,
                                   int type,
                                   const char *uri,
                                   unsigned int flags)
{
    testConnPtr privconn = dom->conn->privateData;
    virDomainObjPtr privdom;
    char *ret = NULL;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, NULL);

    testDriverLock(privconn);
    privdom = virDomainObjListFindByName(privconn->domains,
                                         dom->name);
    testDriverUnlock(privconn);

    if (privdom == NULL) {
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
        goto cleanup;
    }

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

2985
 cleanup:
2986
    virDomainObjEndAPI(&privdom);
2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015
    return ret;
}

static int testDomainSetMetadata(virDomainPtr dom,
                                 int type,
                                 const char *metadata,
                                 const char *key,
                                 const char *uri,
                                 unsigned int flags)
{
    testConnPtr privconn = dom->conn->privateData;
    virDomainObjPtr privdom;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

    testDriverLock(privconn);
    privdom = virDomainObjListFindByName(privconn->domains,
                                         dom->name);
    testDriverUnlock(privconn);

    if (privdom == NULL) {
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
        goto cleanup;
    }

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

3018
 cleanup:
3019
    virDomainObjEndAPI(&privdom);
3020 3021 3022 3023
    return ret;
}


3024 3025
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
3026 3027
                                      int startCell, int maxCells)
{
3028
    testConnPtr privconn = conn->privateData;
3029 3030
    int cell;
    size_t i;
3031
    int ret = -1;
3032

3033
    testDriverLock(privconn);
3034
    if (startCell > privconn->numCells) {
3035 3036
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("Range exceeds available cells"));
3037
        goto cleanup;
3038 3039
    }

3040 3041 3042 3043
    for (cell = startCell, i = 0;
         (cell < privconn->numCells && i < maxCells);
         ++cell, ++i) {
        freemems[i] = privconn->cells[cell].mem;
3044
    }
3045
    ret = i;
3046

3047
 cleanup:
3048
    testDriverUnlock(privconn);
3049
    return ret;
3050 3051 3052
}


3053 3054
static int testDomainCreateWithFlags(virDomainPtr domain, unsigned int flags)
{
3055 3056
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
3057
    virObjectEventPtr event = NULL;
3058
    int ret = -1;
3059

3060 3061
    virCheckFlags(0, -1);

3062
    testDriverLock(privconn);
3063 3064
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
3065 3066

    if (privdom == NULL) {
3067
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3068
        goto cleanup;
3069
    }
3070

J
Jiri Denemark 已提交
3071
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_SHUTOFF) {
3072 3073
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Domain '%s' is already running"), domain->name);
3074
        goto cleanup;
3075 3076
    }

3077
    if (testDomainStartState(privconn, privdom,
J
Jiri Denemark 已提交
3078
                             VIR_DOMAIN_RUNNING_BOOTED) < 0)
3079 3080 3081
        goto cleanup;
    domain->id = privdom->def->id;

3082
    event = virDomainEventLifecycleNewFromObj(privdom,
3083 3084
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
3085
    ret = 0;
3086

3087
 cleanup:
3088
    virDomainObjEndAPI(&privdom);
3089
    if (event)
3090
        testObjectEventQueue(privconn, event);
3091
    testDriverUnlock(privconn);
3092
    return ret;
3093 3094
}

3095 3096
static int testDomainCreate(virDomainPtr domain)
{
3097 3098 3099
    return testDomainCreateWithFlags(domain, 0);
}

3100 3101 3102
static int testDomainUndefineFlags(virDomainPtr domain,
                                   unsigned int flags)
{
3103 3104
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
3105
    virObjectEventPtr event = NULL;
3106
    int nsnapshots;
3107
    int ret = -1;
3108

3109 3110
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
                  VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
3111

3112
    testDriverLock(privconn);
3113 3114
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
3115 3116

    if (privdom == NULL) {
3117
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3118
        goto cleanup;
3119
    }
3120

C
Cole Robinson 已提交
3121 3122 3123 3124 3125 3126 3127 3128
    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;
    }

3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146
    /* 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. */
    }

3147
    event = virDomainEventLifecycleNewFromObj(privdom,
3148 3149
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
C
Cole Robinson 已提交
3150 3151
    privdom->hasManagedSave = false;

3152
    if (virDomainObjIsActive(privdom))
3153
        privdom->persistent = 0;
3154 3155
    else
        virDomainObjListRemove(privconn->domains, privdom);
3156

3157
    ret = 0;
3158

3159
 cleanup:
3160
    virDomainObjEndAPI(&privdom);
3161
    if (event)
3162
        testObjectEventQueue(privconn, event);
3163
    testDriverUnlock(privconn);
3164
    return ret;
3165 3166
}

3167 3168 3169 3170 3171
static int testDomainUndefine(virDomainPtr domain)
{
    return testDomainUndefineFlags(domain, 0);
}

3172 3173 3174
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
3175 3176
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
3177
    int ret = -1;
3178

3179
    testDriverLock(privconn);
3180 3181
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
3182
    testDriverUnlock(privconn);
3183 3184

    if (privdom == NULL) {
3185
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3186
        goto cleanup;
3187 3188
    }

3189
    *autostart = privdom->autostart;
3190 3191
    ret = 0;

3192
 cleanup:
3193
    virDomainObjEndAPI(&privdom);
3194
    return ret;
3195 3196 3197 3198 3199 3200
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
3201 3202
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
3203
    int ret = -1;
3204

3205
    testDriverLock(privconn);
3206 3207
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
3208
    testDriverUnlock(privconn);
3209 3210

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

3215
    privdom->autostart = autostart ? 1 : 0;
3216 3217
    ret = 0;

3218
 cleanup:
3219
    virDomainObjEndAPI(&privdom);
3220
    return ret;
3221
}
3222

3223
static char *testDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED,
3224 3225
                                        int *nparams)
{
3226 3227
    char *type = NULL;

3228 3229 3230
    if (nparams)
        *nparams = 1;

3231
    ignore_value(VIR_STRDUP(type, "fair"));
3232

3233 3234 3235
    return type;
}

3236
static int
3237 3238 3239 3240
testDomainGetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int *nparams,
                                      unsigned int flags)
3241
{
3242 3243
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
3244
    int ret = -1;
3245

3246 3247
    virCheckFlags(0, -1);

3248
    testDriverLock(privconn);
3249 3250
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
3251
    testDriverUnlock(privconn);
3252 3253

    if (privdom == NULL) {
3254
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3255
        goto cleanup;
3256 3257
    }

3258 3259
    if (virTypedParameterAssign(params, VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, 50) < 0)
3260
        goto cleanup;
3261 3262
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
3263 3264

    *nparams = 1;
3265 3266
    ret = 0;

3267
 cleanup:
3268
    virDomainObjEndAPI(&privdom);
3269
    return ret;
3270
}
3271

3272
static int
3273 3274 3275
testDomainGetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int *nparams)
3276
{
3277
    return testDomainGetSchedulerParametersFlags(domain, params, nparams, 0);
3278
}
3279

3280
static int
3281 3282 3283 3284
testDomainSetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int nparams,
                                      unsigned int flags)
3285
{
3286 3287
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
3288 3289
    int ret = -1;
    size_t i;
3290

3291
    virCheckFlags(0, -1);
3292 3293 3294 3295
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
3296
        return -1;
3297

3298
    testDriverLock(privconn);
3299 3300
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
3301
    testDriverUnlock(privconn);
3302 3303

    if (privdom == NULL) {
3304
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3305
        goto cleanup;
3306 3307
    }

3308
    for (i = 0; i < nparams; i++) {
3309 3310 3311
        if (STREQ(params[i].field, VIR_DOMAIN_SCHEDULER_WEIGHT)) {
            /* XXX */
            /*privdom->weight = params[i].value.ui;*/
3312
        }
3313
    }
3314

3315 3316
    ret = 0;

3317
 cleanup:
3318
    virDomainObjEndAPI(&privdom);
3319
    return ret;
3320 3321
}

3322
static int
3323 3324 3325
testDomainSetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int nparams)
3326
{
3327
    return testDomainSetSchedulerParametersFlags(domain, params, nparams, 0);
3328 3329
}

3330 3331
static int testDomainBlockStats(virDomainPtr domain,
                                const char *path,
3332
                                virDomainBlockStatsPtr stats)
3333 3334 3335 3336 3337
{
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
3338
    int ret = -1;
3339

3340 3341 3342 3343 3344 3345
    if (!*path) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("summary statistics are not supported yet"));
        return ret;
    }

3346
    testDriverLock(privconn);
3347 3348
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
3349 3350 3351
    testDriverUnlock(privconn);

    if (privdom == NULL) {
3352
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3353 3354 3355
        goto error;
    }

3356
    if (virDomainDiskIndexByName(privdom->def, path, false) < 0) {
3357 3358
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path: %s"), path);
3359 3360 3361 3362
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
3363
        virReportSystemError(errno,
3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376
                             "%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;
3377
 error:
3378
    virDomainObjEndAPI(&privdom);
3379 3380 3381 3382 3383
    return ret;
}

static int testDomainInterfaceStats(virDomainPtr domain,
                                    const char *path,
3384
                                    virDomainInterfaceStatsPtr stats)
3385 3386 3387 3388 3389
{
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
3390 3391
    size_t i;
    int found = 0, ret = -1;
3392 3393

    testDriverLock(privconn);
3394 3395
    privdom = virDomainObjListFindByName(privconn->domains,
                                         domain->name);
3396 3397 3398
    testDriverUnlock(privconn);

    if (privdom == NULL) {
3399
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3400 3401 3402
        goto error;
    }

3403
    for (i = 0; i < privdom->def->nnets; i++) {
3404
        if (privdom->def->nets[i]->ifname &&
3405
            STREQ(privdom->def->nets[i]->ifname, path)) {
3406 3407 3408 3409 3410 3411
            found = 1;
            break;
        }
    }

    if (!found) {
3412 3413
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path, '%s' is not a known interface"), path);
3414 3415 3416 3417
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
3418
        virReportSystemError(errno,
3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434
                             "%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;
3435
 error:
3436
    virDomainObjEndAPI(&privdom);
3437 3438 3439
    return ret;
}

3440

3441 3442
static virNetworkPtr testNetworkLookupByUUID(virConnectPtr conn,
                                             const unsigned char *uuid)
3443
{
3444 3445
    testConnPtr privconn = conn->privateData;
    virNetworkObjPtr net;
3446
    virNetworkPtr ret = NULL;
3447

3448
    net = virNetworkObjFindByUUID(privconn->networks, uuid);
3449
    if (net == NULL) {
3450
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3451
        goto cleanup;
3452 3453
    }

3454 3455
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

3456
 cleanup:
3457
    virNetworkObjEndAPI(&net);
3458
    return ret;
3459
}
3460

3461
static virNetworkPtr testNetworkLookupByName(virConnectPtr conn,
3462
                                             const char *name)
3463
{
3464
    testConnPtr privconn = conn->privateData;
3465 3466
    virNetworkObjPtr net;
    virNetworkPtr ret = NULL;
3467

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

3474 3475
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

3476
 cleanup:
3477
    virNetworkObjEndAPI(&net);
3478
    return ret;
3479 3480 3481
}


3482 3483
static int testConnectNumOfNetworks(virConnectPtr conn)
{
3484
    testConnPtr privconn = conn->privateData;
3485
    int numActive;
3486

3487 3488
    numActive = virNetworkObjListNumOfNetworks(privconn->networks,
                                               true, NULL, conn);
3489
    return numActive;
3490 3491
}

3492
static int testConnectListNetworks(virConnectPtr conn, char **const names, int nnames) {
3493
    testConnPtr privconn = conn->privateData;
3494
    int n;
3495

3496 3497
    n = virNetworkObjListGetNames(privconn->networks,
                                  true, names, nnames, NULL, conn);
3498
    return n;
3499 3500
}

3501 3502
static int testConnectNumOfDefinedNetworks(virConnectPtr conn)
{
3503
    testConnPtr privconn = conn->privateData;
3504
    int numInactive;
3505

3506 3507
    numInactive = virNetworkObjListNumOfNetworks(privconn->networks,
                                                 false, NULL, conn);
3508
    return numInactive;
3509 3510
}

3511
static int testConnectListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
3512
    testConnPtr privconn = conn->privateData;
3513
    int n;
3514

3515 3516
    n = virNetworkObjListGetNames(privconn->networks,
                                  false, names, nnames, NULL, conn);
3517
    return n;
3518 3519
}

3520
static int
3521
testConnectListAllNetworks(virConnectPtr conn,
3522 3523 3524 3525 3526 3527 3528
                           virNetworkPtr **nets,
                           unsigned int flags)
{
    testConnPtr privconn = conn->privateData;

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

3529
    return virNetworkObjListExport(conn, privconn->networks, nets, NULL, flags);
3530
}
3531 3532 3533 3534 3535 3536 3537

static int testNetworkIsActive(virNetworkPtr net)
{
    testConnPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
    int ret = -1;

3538
    obj = virNetworkObjFindByUUID(privconn->networks, net->uuid);
3539
    if (!obj) {
3540
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3541 3542 3543 3544
        goto cleanup;
    }
    ret = virNetworkObjIsActive(obj);

3545
 cleanup:
3546
    virNetworkObjEndAPI(&obj);
3547 3548 3549 3550 3551 3552 3553 3554 3555
    return ret;
}

static int testNetworkIsPersistent(virNetworkPtr net)
{
    testConnPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
    int ret = -1;

3556
    obj = virNetworkObjFindByUUID(privconn->networks, net->uuid);
3557
    if (!obj) {
3558
        virReportError(VIR_ERR_NO_NETWORK, NULL);
3559 3560 3561 3562
        goto cleanup;
    }
    ret = obj->persistent;

3563
 cleanup:
3564
    virNetworkObjEndAPI(&obj);
3565 3566 3567 3568
    return ret;
}


3569 3570
static virNetworkPtr testNetworkCreateXML(virConnectPtr conn, const char *xml)
{
3571
    testConnPtr privconn = conn->privateData;
3572
    virNetworkDefPtr def;
3573
    virNetworkObjPtr net = NULL;
3574
    virNetworkPtr ret = NULL;
3575
    virObjectEventPtr event = NULL;
3576

3577
    if ((def = virNetworkDefParseString(xml)) == NULL)
3578
        goto cleanup;
3579

3580 3581 3582
    if (!(net = virNetworkAssignDef(privconn->networks, def,
                                    VIR_NETWORK_OBJ_LIST_ADD_LIVE |
                                    VIR_NETWORK_OBJ_LIST_ADD_CHECK_LIVE)))
3583 3584
        goto cleanup;
    def = NULL;
3585
    net->active = 1;
3586

3587
    event = virNetworkEventLifecycleNew(net->def->name, net->def->uuid,
3588 3589
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3590

3591
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3592

3593
 cleanup:
3594
    virNetworkDefFree(def);
3595 3596
    if (event)
        testObjectEventQueue(privconn, event);
3597
    virNetworkObjEndAPI(&net);
3598
    return ret;
3599 3600
}

3601
static
3602
virNetworkPtr testNetworkDefineXML(virConnectPtr conn, const char *xml)
3603
{
3604
    testConnPtr privconn = conn->privateData;
3605
    virNetworkDefPtr def;
3606
    virNetworkObjPtr net = NULL;
3607
    virNetworkPtr ret = NULL;
3608
    virObjectEventPtr event = NULL;
3609

3610
    if ((def = virNetworkDefParseString(xml)) == NULL)
3611
        goto cleanup;
3612

3613
    if (!(net = virNetworkAssignDef(privconn->networks, def, 0)))
3614 3615
        goto cleanup;
    def = NULL;
3616

3617
    event = virNetworkEventLifecycleNew(net->def->name, net->def->uuid,
3618 3619
                                        VIR_NETWORK_EVENT_DEFINED,
                                        0);
3620

3621
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3622

3623
 cleanup:
3624
    virNetworkDefFree(def);
3625 3626
    if (event)
        testObjectEventQueue(privconn, event);
3627
    virNetworkObjEndAPI(&net);
3628
    return ret;
3629 3630
}

3631 3632
static int testNetworkUndefine(virNetworkPtr network)
{
3633 3634
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3635
    int ret = -1;
3636
    virObjectEventPtr event = NULL;
3637

3638
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3639 3640

    if (privnet == NULL) {
3641
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3642
        goto cleanup;
3643
    }
3644

D
Daniel P. Berrange 已提交
3645
    if (virNetworkObjIsActive(privnet)) {
3646 3647
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is still running"), network->name);
3648
        goto cleanup;
3649 3650
    }

3651
    event = virNetworkEventLifecycleNew(network->name, network->uuid,
3652 3653
                                        VIR_NETWORK_EVENT_UNDEFINED,
                                        0);
3654

3655
    virNetworkRemoveInactive(privconn->networks, privnet);
3656
    ret = 0;
3657

3658
 cleanup:
3659 3660
    if (event)
        testObjectEventQueue(privconn, event);
3661
    virNetworkObjEndAPI(&privnet);
3662
    return ret;
3663 3664
}

3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680
static int
testNetworkUpdate(virNetworkPtr net,
                  unsigned int command,
                  unsigned int section,
                  int parentIndex,
                  const char *xml,
                  unsigned int flags)
{
    testConnPtr privconn = net->conn->privateData;
    virNetworkObjPtr network = NULL;
    int isActive, ret = -1;

    virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
                  VIR_NETWORK_UPDATE_AFFECT_CONFIG,
                  -1);

3681
    network = virNetworkObjFindByUUID(privconn->networks, net->uuid);
3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705
    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;
3706
 cleanup:
3707
    virNetworkObjEndAPI(&network);
3708 3709 3710
    return ret;
}

3711 3712
static int testNetworkCreate(virNetworkPtr network)
{
3713 3714
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3715
    int ret = -1;
3716
    virObjectEventPtr event = NULL;
3717

3718
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3719
    if (privnet == NULL) {
3720
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3721
        goto cleanup;
3722
    }
3723

D
Daniel P. Berrange 已提交
3724
    if (virNetworkObjIsActive(privnet)) {
3725 3726
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Network '%s' is already running"), network->name);
3727
        goto cleanup;
3728 3729
    }

3730
    privnet->active = 1;
3731
    event = virNetworkEventLifecycleNew(privnet->def->name, privnet->def->uuid,
3732 3733
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
3734
    ret = 0;
3735

3736
 cleanup:
3737 3738
    if (event)
        testObjectEventQueue(privconn, event);
3739
    virNetworkObjEndAPI(&privnet);
3740
    return ret;
3741 3742
}

3743 3744
static int testNetworkDestroy(virNetworkPtr network)
{
3745 3746
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3747
    int ret = -1;
3748
    virObjectEventPtr event = NULL;
3749

3750
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3751
    if (privnet == NULL) {
3752
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3753
        goto cleanup;
3754
    }
3755

3756
    privnet->active = 0;
3757
    event = virNetworkEventLifecycleNew(privnet->def->name, privnet->def->uuid,
3758 3759
                                        VIR_NETWORK_EVENT_STOPPED,
                                        0);
3760
    if (!privnet->persistent)
3761
        virNetworkRemoveInactive(privconn->networks, privnet);
3762

3763 3764
    ret = 0;

3765
 cleanup:
3766 3767
    if (event)
        testObjectEventQueue(privconn, event);
3768
    virNetworkObjEndAPI(&privnet);
3769
    return ret;
3770 3771
}

3772
static char *testNetworkGetXMLDesc(virNetworkPtr network,
E
Eric Blake 已提交
3773
                                   unsigned int flags)
3774
{
3775 3776
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3777
    char *ret = NULL;
3778

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

3781
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3782
    if (privnet == NULL) {
3783
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3784
        goto cleanup;
3785
    }
3786

3787
    ret = virNetworkDefFormat(privnet->def, flags);
3788

3789
 cleanup:
3790
    virNetworkObjEndAPI(&privnet);
3791
    return ret;
3792 3793 3794
}

static char *testNetworkGetBridgeName(virNetworkPtr network) {
3795
    testConnPtr privconn = network->conn->privateData;
3796
    char *bridge = NULL;
3797 3798
    virNetworkObjPtr privnet;

3799
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3800
    if (privnet == NULL) {
3801
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3802
        goto cleanup;
3803 3804
    }

3805
    if (!(privnet->def->bridge)) {
3806 3807 3808
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("network '%s' does not have a bridge name."),
                       privnet->def->name);
3809 3810 3811
        goto cleanup;
    }

3812
    ignore_value(VIR_STRDUP(bridge, privnet->def->bridge));
3813

3814
 cleanup:
3815
    virNetworkObjEndAPI(&privnet);
3816 3817 3818 3819
    return bridge;
}

static int testNetworkGetAutostart(virNetworkPtr network,
3820 3821
                                   int *autostart)
{
3822 3823
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3824
    int ret = -1;
3825

3826
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3827
    if (privnet == NULL) {
3828
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3829
        goto cleanup;
3830 3831
    }

3832
    *autostart = privnet->autostart;
3833 3834
    ret = 0;

3835
 cleanup:
3836
    virNetworkObjEndAPI(&privnet);
3837
    return ret;
3838 3839 3840
}

static int testNetworkSetAutostart(virNetworkPtr network,
3841 3842
                                   int autostart)
{
3843 3844
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3845
    int ret = -1;
3846

3847
    privnet = virNetworkObjFindByName(privconn->networks, network->name);
3848
    if (privnet == NULL) {
3849
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3850
        goto cleanup;
3851 3852
    }

3853
    privnet->autostart = autostart ? 1 : 0;
3854 3855
    ret = 0;

3856
 cleanup:
3857
    virNetworkObjEndAPI(&privnet);
3858
    return ret;
3859
}
3860

C
Cole Robinson 已提交
3861

L
Laine Stump 已提交
3862 3863 3864 3865 3866
/*
 * Physical host interface routines
 */


3867
static int testConnectNumOfInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3868 3869
{
    testConnPtr privconn = conn->privateData;
3870 3871
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3872 3873

    testDriverLock(privconn);
3874
    for (i = 0; (i < privconn->ifaces.count); i++) {
L
Laine Stump 已提交
3875
        virInterfaceObjLock(privconn->ifaces.objs[i]);
3876
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i]))
L
Laine Stump 已提交
3877 3878 3879 3880 3881 3882 3883
            count++;
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3884
static int testConnectListInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3885 3886
{
    testConnPtr privconn = conn->privateData;
3887 3888
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3889 3890 3891

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
3892
    for (i = 0; (i < privconn->ifaces.count) && (n < nnames); i++) {
L
Laine Stump 已提交
3893
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3894
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
3895
            if (VIR_STRDUP(names[n++], privconn->ifaces.objs[i]->def->name) < 0) {
L
Laine Stump 已提交
3896
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
3897
                goto error;
L
Laine Stump 已提交
3898 3899 3900 3901 3902 3903 3904 3905
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

3906
 error:
3907
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3908 3909 3910 3911 3912
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

3913
static int testConnectNumOfDefinedInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
3914 3915
{
    testConnPtr privconn = conn->privateData;
3916 3917
    size_t i;
    int count = 0;
L
Laine Stump 已提交
3918 3919

    testDriverLock(privconn);
3920
    for (i = 0; i < privconn->ifaces.count; i++) {
L
Laine Stump 已提交
3921
        virInterfaceObjLock(privconn->ifaces.objs[i]);
3922
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i]))
L
Laine Stump 已提交
3923 3924 3925 3926 3927 3928 3929
            count++;
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

3930
static int testConnectListDefinedInterfaces(virConnectPtr conn, char **const names, int nnames)
L
Laine Stump 已提交
3931 3932
{
    testConnPtr privconn = conn->privateData;
3933 3934
    int n = 0;
    size_t i;
L
Laine Stump 已提交
3935 3936 3937

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
3938
    for (i = 0; (i < privconn->ifaces.count) && (n < nnames); i++) {
L
Laine Stump 已提交
3939
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3940
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
3941
            if (VIR_STRDUP(names[n++], privconn->ifaces.objs[i]->def->name) < 0) {
L
Laine Stump 已提交
3942
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
3943
                goto error;
L
Laine Stump 已提交
3944 3945 3946 3947 3948 3949 3950 3951
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

3952
 error:
3953
    for (n = 0; n < nnames; n++)
L
Laine Stump 已提交
3954 3955 3956 3957 3958
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

3959
static virInterfacePtr testInterfaceLookupByName(virConnectPtr conn,
L
Laine Stump 已提交
3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970
                                                 const char *name)
{
    testConnPtr privconn = conn->privateData;
    virInterfaceObjPtr iface;
    virInterfacePtr ret = NULL;

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

    if (iface == NULL) {
3971
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3972 3973 3974 3975 3976
        goto cleanup;
    }

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

3977
 cleanup:
L
Laine Stump 已提交
3978 3979 3980 3981 3982
    if (iface)
        virInterfaceObjUnlock(iface);
    return ret;
}

3983
static virInterfacePtr testInterfaceLookupByMACString(virConnectPtr conn,
L
Laine Stump 已提交
3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995
                                                      const char *mac)
{
    testConnPtr privconn = conn->privateData;
    virInterfaceObjPtr iface;
    int ifacect;
    virInterfacePtr ret = NULL;

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

    if (ifacect == 0) {
3996
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3997 3998 3999 4000
        goto cleanup;
    }

    if (ifacect > 1) {
4001
        virReportError(VIR_ERR_MULTIPLE_INTERFACES, NULL);
L
Laine Stump 已提交
4002 4003 4004 4005 4006
        goto cleanup;
    }

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

4007
 cleanup:
L
Laine Stump 已提交
4008 4009 4010 4011 4012
    if (iface)
        virInterfaceObjUnlock(iface);
    return ret;
}

4013 4014 4015 4016 4017 4018 4019 4020 4021 4022
static int testInterfaceIsActive(virInterfacePtr iface)
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virInterfaceFindByName(&privconn->ifaces, iface->name);
    testDriverUnlock(privconn);
    if (!obj) {
4023
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
4024 4025 4026 4027
        goto cleanup;
    }
    ret = virInterfaceObjIsActive(obj);

4028
 cleanup:
4029 4030 4031 4032 4033
    if (obj)
        virInterfaceObjUnlock(obj);
    return ret;
}

4034
static int testInterfaceChangeBegin(virConnectPtr conn,
E
Eric Blake 已提交
4035
                                    unsigned int flags)
4036 4037 4038 4039
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

E
Eric Blake 已提交
4040 4041
    virCheckFlags(0, -1);

4042 4043
    testDriverLock(privconn);
    if (privconn->transaction_running) {
4044
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
4045
                       _("there is another transaction running."));
4046 4047 4048 4049 4050 4051 4052 4053 4054 4055
        goto cleanup;
    }

    privconn->transaction_running = true;

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

    ret = 0;
4056
 cleanup:
4057 4058 4059 4060 4061
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceChangeCommit(virConnectPtr conn,
E
Eric Blake 已提交
4062
                                     unsigned int flags)
4063 4064 4065 4066
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

E
Eric Blake 已提交
4067 4068
    virCheckFlags(0, -1);

4069 4070 4071
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
4072
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
4073 4074
                       _("no transaction running, "
                         "nothing to be committed."));
4075 4076 4077 4078 4079 4080 4081 4082
        goto cleanup;
    }

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

    ret = 0;

4083
 cleanup:
4084 4085 4086 4087 4088 4089
    testDriverUnlock(privconn);

    return ret;
}

static int testInterfaceChangeRollback(virConnectPtr conn,
E
Eric Blake 已提交
4090
                                       unsigned int flags)
4091 4092 4093 4094
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

E
Eric Blake 已提交
4095 4096
    virCheckFlags(0, -1);

4097 4098 4099
    testDriverLock(privconn);

    if (!privconn->transaction_running) {
4100
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
4101 4102
                       _("no transaction running, "
                         "nothing to rollback."));
4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115
        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;

4116
 cleanup:
4117 4118 4119
    testDriverUnlock(privconn);
    return ret;
}
4120

L
Laine Stump 已提交
4121
static char *testInterfaceGetXMLDesc(virInterfacePtr iface,
E
Eric Blake 已提交
4122
                                     unsigned int flags)
L
Laine Stump 已提交
4123 4124 4125 4126 4127
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr privinterface;
    char *ret = NULL;

E
Eric Blake 已提交
4128 4129
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
4130 4131 4132 4133 4134 4135
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);
    testDriverUnlock(privconn);

    if (privinterface == NULL) {
4136
        virReportError(VIR_ERR_NO_INTERFACE, __FUNCTION__);
L
Laine Stump 已提交
4137 4138 4139
        goto cleanup;
    }

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

4142
 cleanup:
L
Laine Stump 已提交
4143 4144 4145 4146 4147 4148 4149
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    return ret;
}


static virInterfacePtr testInterfaceDefineXML(virConnectPtr conn, const char *xmlStr,
E
Eric Blake 已提交
4150
                                              unsigned int flags)
L
Laine Stump 已提交
4151 4152 4153 4154 4155 4156
{
    testConnPtr privconn = conn->privateData;
    virInterfaceDefPtr def;
    virInterfaceObjPtr iface = NULL;
    virInterfacePtr ret = NULL;

E
Eric Blake 已提交
4157 4158
    virCheckFlags(0, NULL);

L
Laine Stump 已提交
4159
    testDriverLock(privconn);
4160
    if ((def = virInterfaceDefParseString(xmlStr)) == NULL)
L
Laine Stump 已提交
4161 4162
        goto cleanup;

4163
    if ((iface = virInterfaceAssignDef(&privconn->ifaces, def)) == NULL)
L
Laine Stump 已提交
4164 4165 4166 4167 4168
        goto cleanup;
    def = NULL;

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

4169
 cleanup:
L
Laine Stump 已提交
4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187
    virInterfaceDefFree(def);
    if (iface)
        virInterfaceObjUnlock(iface);
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceUndefine(virInterfacePtr iface)
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr privinterface;
    int ret = -1;

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

    if (privinterface == NULL) {
4188
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
4189 4190 4191 4192 4193 4194 4195
        goto cleanup;
    }

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

4196
 cleanup:
L
Laine Stump 已提交
4197 4198 4199 4200 4201
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceCreate(virInterfacePtr iface,
E
Eric Blake 已提交
4202
                               unsigned int flags)
L
Laine Stump 已提交
4203 4204 4205 4206 4207
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr privinterface;
    int ret = -1;

E
Eric Blake 已提交
4208 4209
    virCheckFlags(0, -1);

L
Laine Stump 已提交
4210 4211 4212 4213 4214
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);

    if (privinterface == NULL) {
4215
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
4216 4217 4218 4219
        goto cleanup;
    }

    if (privinterface->active != 0) {
4220
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
4221 4222 4223 4224 4225 4226
        goto cleanup;
    }

    privinterface->active = 1;
    ret = 0;

4227
 cleanup:
L
Laine Stump 已提交
4228 4229 4230 4231 4232 4233 4234
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceDestroy(virInterfacePtr iface,
E
Eric Blake 已提交
4235
                                unsigned int flags)
L
Laine Stump 已提交
4236 4237 4238 4239 4240
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr privinterface;
    int ret = -1;

E
Eric Blake 已提交
4241 4242
    virCheckFlags(0, -1);

L
Laine Stump 已提交
4243 4244 4245 4246 4247
    testDriverLock(privconn);
    privinterface = virInterfaceFindByName(&privconn->ifaces,
                                           iface->name);

    if (privinterface == NULL) {
4248
        virReportError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
4249 4250 4251 4252
        goto cleanup;
    }

    if (privinterface->active == 0) {
4253
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
4254 4255 4256 4257 4258 4259
        goto cleanup;
    }

    privinterface->active = 0;
    ret = 0;

4260
 cleanup:
L
Laine Stump 已提交
4261 4262 4263 4264 4265 4266 4267 4268
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    testDriverUnlock(privconn);
    return ret;
}



C
Cole Robinson 已提交
4269 4270 4271 4272
/*
 * Storage Driver routines
 */

4273

4274 4275
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool)
{
C
Cole Robinson 已提交
4276 4277 4278 4279 4280

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

4281
    return VIR_STRDUP(pool->configFile, "");
C
Cole Robinson 已提交
4282 4283
}

4284

C
Cole Robinson 已提交
4285 4286
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
4287 4288
                            const unsigned char *uuid)
{
4289
    testConnPtr privconn = conn->privateData;
4290 4291
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4292

4293
    testDriverLock(privconn);
4294
    pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid);
4295
    testDriverUnlock(privconn);
4296 4297

    if (pool == NULL) {
4298
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4299
        goto cleanup;
C
Cole Robinson 已提交
4300 4301
    }

4302 4303
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4304

4305
 cleanup:
4306 4307
    if (pool)
        virStoragePoolObjUnlock(pool);
4308
    return ret;
C
Cole Robinson 已提交
4309 4310 4311 4312
}

static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
4313 4314
                            const char *name)
{
4315
    testConnPtr privconn = conn->privateData;
4316 4317
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4318

4319
    testDriverLock(privconn);
4320
    pool = virStoragePoolObjFindByName(&privconn->pools, name);
4321
    testDriverUnlock(privconn);
4322 4323

    if (pool == NULL) {
4324
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4325
        goto cleanup;
C
Cole Robinson 已提交
4326 4327
    }

4328 4329
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4330

4331
 cleanup:
4332 4333
    if (pool)
        virStoragePoolObjUnlock(pool);
4334
    return ret;
C
Cole Robinson 已提交
4335 4336 4337
}

static virStoragePoolPtr
4338 4339
testStoragePoolLookupByVolume(virStorageVolPtr vol)
{
C
Cole Robinson 已提交
4340 4341 4342 4343
    return testStoragePoolLookupByName(vol->conn, vol->pool);
}

static int
4344 4345
testConnectNumOfStoragePools(virConnectPtr conn)
{
4346
    testConnPtr privconn = conn->privateData;
4347 4348
    int numActive = 0;
    size_t i;
C
Cole Robinson 已提交
4349

4350
    testDriverLock(privconn);
4351
    for (i = 0; i < privconn->pools.count; i++)
C
Cole Robinson 已提交
4352 4353
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numActive++;
4354
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4355 4356 4357 4358 4359

    return numActive;
}

static int
4360 4361
testConnectListStoragePools(virConnectPtr conn,
                            char **const names,
4362 4363
                            int nnames)
{
4364
    testConnPtr privconn = conn->privateData;
4365 4366
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
4367

4368
    testDriverLock(privconn);
C
Cole Robinson 已提交
4369
    memset(names, 0, sizeof(*names)*nnames);
4370
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
4371
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4372
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
4373
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
4374
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
4375
            goto error;
4376 4377 4378 4379
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4380 4381 4382

    return n;

4383
 error:
4384
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
4385
        VIR_FREE(names[n]);
4386
    testDriverUnlock(privconn);
4387
    return -1;
C
Cole Robinson 已提交
4388 4389 4390
}

static int
4391 4392
testConnectNumOfDefinedStoragePools(virConnectPtr conn)
{
4393
    testConnPtr privconn = conn->privateData;
4394 4395
    int numInactive = 0;
    size_t i;
C
Cole Robinson 已提交
4396

4397
    testDriverLock(privconn);
4398
    for (i = 0; i < privconn->pools.count; i++) {
4399
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4400 4401
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numInactive++;
4402 4403 4404
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4405 4406 4407 4408 4409

    return numInactive;
}

static int
4410 4411
testConnectListDefinedStoragePools(virConnectPtr conn,
                                   char **const names,
4412 4413
                                   int nnames)
{
4414
    testConnPtr privconn = conn->privateData;
4415 4416
    int n = 0;
    size_t i;
C
Cole Robinson 已提交
4417

4418
    testDriverLock(privconn);
C
Cole Robinson 已提交
4419
    memset(names, 0, sizeof(*names)*nnames);
4420
    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
4421
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4422
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
4423
            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
4424
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
4425
            goto error;
4426 4427 4428 4429
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4430 4431 4432

    return n;

4433
 error:
4434
    for (n = 0; n < nnames; n++)
C
Cole Robinson 已提交
4435
        VIR_FREE(names[n]);
4436
    testDriverUnlock(privconn);
4437
    return -1;
C
Cole Robinson 已提交
4438 4439
}

4440
static int
4441 4442 4443
testConnectListAllStoragePools(virConnectPtr conn,
                               virStoragePoolPtr **pools,
                               unsigned int flags)
4444 4445 4446 4447 4448 4449 4450
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

    testDriverLock(privconn);
4451 4452
    ret = virStoragePoolObjListExport(conn, privconn->pools, pools,
                                      NULL, flags);
4453 4454 4455 4456
    testDriverUnlock(privconn);

    return ret;
}
C
Cole Robinson 已提交
4457

4458 4459 4460 4461 4462 4463 4464 4465 4466 4467
static int testStoragePoolIsActive(virStoragePoolPtr pool)
{
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virStoragePoolObjFindByUUID(&privconn->pools, pool->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
4468
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4469 4470 4471 4472
        goto cleanup;
    }
    ret = virStoragePoolObjIsActive(obj);

4473
 cleanup:
4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488
    if (obj)
        virStoragePoolObjUnlock(obj);
    return ret;
}

static int testStoragePoolIsPersistent(virStoragePoolPtr pool)
{
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virStoragePoolObjFindByUUID(&privconn->pools, pool->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
4489
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
4490 4491 4492 4493
        goto cleanup;
    }
    ret = obj->configFile ? 1 : 0;

4494
 cleanup:
4495 4496 4497 4498 4499 4500 4501
    if (obj)
        virStoragePoolObjUnlock(obj);
    return ret;
}



C
Cole Robinson 已提交
4502
static int
4503 4504
testStoragePoolCreate(virStoragePoolPtr pool,
                      unsigned int flags)
E
Eric Blake 已提交
4505
{
4506 4507
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4508
    int ret = -1;
4509

E
Eric Blake 已提交
4510 4511
    virCheckFlags(0, -1);

4512
    testDriverLock(privconn);
4513 4514
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4515
    testDriverUnlock(privconn);
4516 4517

    if (privpool == NULL) {
4518
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4519
        goto cleanup;
4520 4521
    }

4522
    if (virStoragePoolObjIsActive(privpool)) {
4523 4524
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4525 4526
        goto cleanup;
    }
C
Cole Robinson 已提交
4527 4528

    privpool->active = 1;
4529
    ret = 0;
C
Cole Robinson 已提交
4530

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

static char *
4538 4539 4540 4541
testConnectFindStoragePoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type,
                                  const char *srcSpec,
                                  unsigned int flags)
C
Cole Robinson 已提交
4542
{
4543 4544 4545 4546
    virStoragePoolSourcePtr source = NULL;
    int pool_type;
    char *ret = NULL;

E
Eric Blake 已提交
4547 4548
    virCheckFlags(0, NULL);

4549 4550
    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
4551 4552
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
4553 4554 4555 4556
        goto cleanup;
    }

    if (srcSpec) {
4557
        source = virStoragePoolDefParseSourceString(srcSpec, pool_type);
4558 4559 4560 4561 4562 4563 4564
        if (!source)
            goto cleanup;
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
4565
        ignore_value(VIR_STRDUP(ret, defaultPoolSourcesLogicalXML));
4566 4567 4568
        break;

    case VIR_STORAGE_POOL_NETFS:
4569
        if (!source || !source->hosts[0].name) {
4570 4571
            virReportError(VIR_ERR_INVALID_ARG,
                           "%s", _("hostname must be specified for netfs sources"));
4572 4573 4574
            goto cleanup;
        }

4575 4576
        ignore_value(virAsprintf(&ret, defaultPoolSourcesNetFSXML,
                                 source->hosts[0].name));
4577 4578 4579
        break;

    default:
4580 4581
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source discovery"), type);
4582 4583
    }

4584
 cleanup:
4585 4586
    virStoragePoolSourceFree(source);
    return ret;
C
Cole Robinson 已提交
4587 4588 4589 4590
}


static virStoragePoolPtr
4591 4592 4593
testStoragePoolCreateXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4594
{
4595
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4596
    virStoragePoolDefPtr def;
4597
    virStoragePoolObjPtr pool = NULL;
4598
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4599

E
Eric Blake 已提交
4600 4601
    virCheckFlags(0, NULL);

4602
    testDriverLock(privconn);
4603
    if (!(def = virStoragePoolDefParseString(xml)))
4604
        goto cleanup;
C
Cole Robinson 已提交
4605

4606 4607 4608 4609
    pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid);
    if (!pool)
        pool = virStoragePoolObjFindByName(&privconn->pools, def->name);
    if (pool) {
4610 4611
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("storage pool already exists"));
4612
        goto cleanup;
C
Cole Robinson 已提交
4613 4614
    }

4615
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4616
        goto cleanup;
4617
    def = NULL;
C
Cole Robinson 已提交
4618

4619
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4620
        virStoragePoolObjRemove(&privconn->pools, pool);
4621 4622
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4623 4624 4625
    }
    pool->active = 1;

4626 4627
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4628

4629
 cleanup:
4630
    virStoragePoolDefFree(def);
4631 4632 4633
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4634
    return ret;
C
Cole Robinson 已提交
4635 4636 4637
}

static virStoragePoolPtr
4638 4639 4640
testStoragePoolDefineXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
4641
{
4642
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4643
    virStoragePoolDefPtr def;
4644
    virStoragePoolObjPtr pool = NULL;
4645
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
4646

E
Eric Blake 已提交
4647 4648
    virCheckFlags(0, NULL);

4649
    testDriverLock(privconn);
4650
    if (!(def = virStoragePoolDefParseString(xml)))
4651
        goto cleanup;
C
Cole Robinson 已提交
4652 4653 4654 4655 4656

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

4657
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
4658 4659
        goto cleanup;
    def = NULL;
C
Cole Robinson 已提交
4660

4661
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
4662
        virStoragePoolObjRemove(&privconn->pools, pool);
4663 4664
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
4665 4666
    }

4667 4668
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
4669

4670
 cleanup:
4671
    virStoragePoolDefFree(def);
4672 4673 4674
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
4675
    return ret;
C
Cole Robinson 已提交
4676 4677 4678
}

static int
4679 4680
testStoragePoolUndefine(virStoragePoolPtr pool)
{
4681 4682
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4683
    int ret = -1;
4684

4685
    testDriverLock(privconn);
4686 4687 4688 4689
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
4690
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4691
        goto cleanup;
4692 4693
    }

4694
    if (virStoragePoolObjIsActive(privpool)) {
4695 4696
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4697 4698
        goto cleanup;
    }
C
Cole Robinson 已提交
4699 4700

    virStoragePoolObjRemove(&privconn->pools, privpool);
4701
    ret = 0;
C
Cole Robinson 已提交
4702

4703
 cleanup:
4704 4705 4706
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
4707
    return ret;
C
Cole Robinson 已提交
4708 4709 4710
}

static int
4711
testStoragePoolBuild(virStoragePoolPtr pool,
E
Eric Blake 已提交
4712 4713
                     unsigned int flags)
{
4714 4715
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4716
    int ret = -1;
4717

E
Eric Blake 已提交
4718 4719
    virCheckFlags(0, -1);

4720
    testDriverLock(privconn);
4721 4722
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4723
    testDriverUnlock(privconn);
4724 4725

    if (privpool == NULL) {
4726
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4727
        goto cleanup;
4728 4729
    }

4730
    if (virStoragePoolObjIsActive(privpool)) {
4731 4732
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4733 4734
        goto cleanup;
    }
4735
    ret = 0;
C
Cole Robinson 已提交
4736

4737
 cleanup:
4738 4739
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4740
    return ret;
C
Cole Robinson 已提交
4741 4742 4743 4744
}


static int
4745 4746
testStoragePoolDestroy(virStoragePoolPtr pool)
{
4747 4748
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4749
    int ret = -1;
4750

4751
    testDriverLock(privconn);
4752 4753 4754 4755
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
4756
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4757
        goto cleanup;
4758 4759 4760
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4761 4762
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4763
        goto cleanup;
4764
    }
C
Cole Robinson 已提交
4765 4766 4767

    privpool->active = 0;

4768
    if (privpool->configFile == NULL) {
C
Cole Robinson 已提交
4769
        virStoragePoolObjRemove(&privconn->pools, privpool);
4770 4771
        privpool = NULL;
    }
4772
    ret = 0;
C
Cole Robinson 已提交
4773

4774
 cleanup:
4775 4776 4777
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
4778
    return ret;
C
Cole Robinson 已提交
4779 4780 4781 4782
}


static int
4783
testStoragePoolDelete(virStoragePoolPtr pool,
E
Eric Blake 已提交
4784 4785
                      unsigned int flags)
{
4786 4787
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4788
    int ret = -1;
4789

E
Eric Blake 已提交
4790 4791
    virCheckFlags(0, -1);

4792
    testDriverLock(privconn);
4793 4794
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4795
    testDriverUnlock(privconn);
4796 4797

    if (privpool == NULL) {
4798
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4799 4800 4801 4802
        goto cleanup;
    }

    if (virStoragePoolObjIsActive(privpool)) {
4803 4804
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is already active"), pool->name);
4805
        goto cleanup;
4806 4807
    }

4808
    ret = 0;
C
Cole Robinson 已提交
4809

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


static int
4818
testStoragePoolRefresh(virStoragePoolPtr pool,
E
Eric Blake 已提交
4819 4820
                       unsigned int flags)
{
4821 4822
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4823
    int ret = -1;
4824

E
Eric Blake 已提交
4825 4826
    virCheckFlags(0, -1);

4827
    testDriverLock(privconn);
4828 4829
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4830
    testDriverUnlock(privconn);
4831 4832

    if (privpool == NULL) {
4833
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4834
        goto cleanup;
4835 4836 4837
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4838 4839
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4840
        goto cleanup;
4841
    }
4842
    ret = 0;
C
Cole Robinson 已提交
4843

4844
 cleanup:
4845 4846
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4847
    return ret;
C
Cole Robinson 已提交
4848 4849 4850 4851
}


static int
4852
testStoragePoolGetInfo(virStoragePoolPtr pool,
4853 4854
                       virStoragePoolInfoPtr info)
{
4855 4856
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4857
    int ret = -1;
4858

4859
    testDriverLock(privconn);
4860 4861
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4862
    testDriverUnlock(privconn);
4863 4864

    if (privpool == NULL) {
4865
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4866
        goto cleanup;
4867
    }
C
Cole Robinson 已提交
4868 4869 4870 4871 4872 4873 4874 4875 4876

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

4879
 cleanup:
4880 4881
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4882
    return ret;
C
Cole Robinson 已提交
4883 4884 4885
}

static char *
4886
testStoragePoolGetXMLDesc(virStoragePoolPtr pool,
E
Eric Blake 已提交
4887 4888
                          unsigned int flags)
{
4889 4890
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4891
    char *ret = NULL;
4892

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

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

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

4905
    ret = virStoragePoolDefFormat(privpool->def);
4906

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

static int
4914
testStoragePoolGetAutostart(virStoragePoolPtr pool,
4915 4916
                            int *autostart)
{
4917 4918
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4919
    int ret = -1;
4920

4921
    testDriverLock(privconn);
4922 4923
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4924
    testDriverUnlock(privconn);
4925 4926

    if (privpool == NULL) {
4927
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4928
        goto cleanup;
4929
    }
C
Cole Robinson 已提交
4930 4931 4932 4933 4934 4935

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

4938
 cleanup:
4939 4940
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4941
    return ret;
C
Cole Robinson 已提交
4942 4943 4944
}

static int
4945
testStoragePoolSetAutostart(virStoragePoolPtr pool,
4946 4947
                            int autostart)
{
4948 4949
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4950
    int ret = -1;
4951

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

    if (privpool == NULL) {
4958
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4959
        goto cleanup;
4960
    }
C
Cole Robinson 已提交
4961 4962

    if (!privpool->configFile) {
4963 4964
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("pool has no config file"));
4965
        goto cleanup;
C
Cole Robinson 已提交
4966 4967 4968 4969
    }

    autostart = (autostart != 0);
    privpool->autostart = autostart;
4970 4971
    ret = 0;

4972
 cleanup:
4973 4974
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4975
    return ret;
C
Cole Robinson 已提交
4976 4977 4978 4979
}


static int
4980 4981
testStoragePoolNumOfVolumes(virStoragePoolPtr pool)
{
4982 4983
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4984
    int ret = -1;
4985

4986
    testDriverLock(privconn);
4987 4988
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4989
    testDriverUnlock(privconn);
4990 4991

    if (privpool == NULL) {
4992
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4993
        goto cleanup;
4994 4995 4996
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4997 4998
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
4999
        goto cleanup;
5000
    }
C
Cole Robinson 已提交
5001

5002 5003
    ret = privpool->volumes.count;

5004
 cleanup:
5005 5006
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5007
    return ret;
C
Cole Robinson 已提交
5008 5009 5010
}

static int
5011
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
5012
                           char **const names,
5013 5014
                           int maxnames)
{
5015 5016
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
5017 5018
    size_t i = 0;
    int n = 0;
C
Cole Robinson 已提交
5019

5020
    memset(names, 0, maxnames * sizeof(*names));
5021 5022

    testDriverLock(privconn);
5023 5024
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
5025
    testDriverUnlock(privconn);
5026 5027

    if (privpool == NULL) {
5028
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5029
        goto cleanup;
5030 5031 5032 5033
    }


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

5039
    for (i = 0; i < privpool->volumes.count && n < maxnames; i++) {
5040
        if (VIR_STRDUP(names[n++], privpool->volumes.objs[i]->name) < 0)
C
Cole Robinson 已提交
5041 5042 5043
            goto cleanup;
    }

5044
    virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
5045 5046 5047
    return n;

 cleanup:
5048
    for (n = 0; n < maxnames; n++)
C
Cole Robinson 已提交
5049 5050
        VIR_FREE(names[i]);

5051
    memset(names, 0, maxnames * sizeof(*names));
5052 5053
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
5054 5055 5056
    return -1;
}

5057 5058 5059
static int
testStoragePoolListAllVolumes(virStoragePoolPtr obj,
                              virStorageVolPtr **vols,
5060 5061
                              unsigned int flags)
{
5062 5063
    testConnPtr privconn = obj->conn->privateData;
    virStoragePoolObjPtr pool;
5064
    size_t i;
5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093
    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;
    }

5094
    if (VIR_ALLOC_N(tmp_vols, pool->volumes.count + 1) < 0)
5095 5096
         goto cleanup;

5097
    for (i = 0; i < pool->volumes.count; i++) {
5098 5099
        if (!(vol = virGetStorageVol(obj->conn, pool->def->name,
                                     pool->volumes.objs[i]->name,
5100 5101
                                     pool->volumes.objs[i]->key,
                                     NULL, NULL)))
5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115
            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]);
        }
5116
        VIR_FREE(tmp_vols);
5117 5118 5119 5120 5121 5122 5123
    }

    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
C
Cole Robinson 已提交
5124 5125

static virStorageVolPtr
5126
testStorageVolLookupByName(virStoragePoolPtr pool,
5127 5128
                           const char *name ATTRIBUTE_UNUSED)
{
5129 5130 5131
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5132
    virStorageVolPtr ret = NULL;
5133

5134
    testDriverLock(privconn);
5135 5136
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
5137
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
5138

5139
    if (privpool == NULL) {
5140
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5141
        goto cleanup;
5142 5143 5144 5145
    }


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

    privvol = virStorageVolDefFindByName(privpool, name);

    if (!privvol) {
5154 5155
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"), name);
5156
        goto cleanup;
C
Cole Robinson 已提交
5157 5158
    }

5159
    ret = virGetStorageVol(pool->conn, privpool->def->name,
5160 5161
                           privvol->name, privvol->key,
                           NULL, NULL);
5162

5163
 cleanup:
5164 5165
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5166
    return ret;
C
Cole Robinson 已提交
5167 5168 5169 5170
}


static virStorageVolPtr
5171
testStorageVolLookupByKey(virConnectPtr conn,
5172 5173
                          const char *key)
{
5174
    testConnPtr privconn = conn->privateData;
5175
    size_t i;
5176
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
5177

5178
    testDriverLock(privconn);
5179
    for (i = 0; i < privconn->pools.count; i++) {
5180
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
5181
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
5182
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
5183 5184
                virStorageVolDefFindByKey(privconn->pools.objs[i], key);

5185 5186 5187 5188
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
5189 5190
                                       privvol->key,
                                       NULL, NULL);
5191
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
5192 5193
                break;
            }
C
Cole Robinson 已提交
5194
        }
5195
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
5196
    }
5197
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
5198

5199
    if (!ret)
5200 5201
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching key '%s'"), key);
5202 5203

    return ret;
C
Cole Robinson 已提交
5204 5205 5206
}

static virStorageVolPtr
5207
testStorageVolLookupByPath(virConnectPtr conn,
5208 5209
                           const char *path)
{
5210
    testConnPtr privconn = conn->privateData;
5211
    size_t i;
5212
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
5213

5214
    testDriverLock(privconn);
5215
    for (i = 0; i < privconn->pools.count; i++) {
5216
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
5217
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
5218
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
5219 5220
                virStorageVolDefFindByPath(privconn->pools.objs[i], path);

5221 5222 5223 5224
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
5225 5226
                                       privvol->key,
                                       NULL, NULL);
5227
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
5228 5229
                break;
            }
C
Cole Robinson 已提交
5230
        }
5231
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
5232
    }
5233
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
5234

5235
    if (!ret)
5236 5237
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching path '%s'"), path);
5238 5239

    return ret;
C
Cole Robinson 已提交
5240 5241 5242
}

static virStorageVolPtr
5243 5244 5245
testStorageVolCreateXML(virStoragePoolPtr pool,
                        const char *xmldesc,
                        unsigned int flags)
E
Eric Blake 已提交
5246
{
5247 5248
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
5249 5250
    virStorageVolDefPtr privvol = NULL;
    virStorageVolPtr ret = NULL;
5251

E
Eric Blake 已提交
5252 5253
    virCheckFlags(0, NULL);

5254
    testDriverLock(privconn);
5255 5256
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
5257
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
5258

5259
    if (privpool == NULL) {
5260
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5261
        goto cleanup;
5262 5263 5264
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5265 5266
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
5267
        goto cleanup;
5268
    }
C
Cole Robinson 已提交
5269

5270
    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
5271
    if (privvol == NULL)
5272
        goto cleanup;
5273 5274

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
5275 5276
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
5277
        goto cleanup;
C
Cole Robinson 已提交
5278 5279 5280
    }

    /* Make sure enough space */
5281
    if ((privpool->def->allocation + privvol->target.allocation) >
C
Cole Robinson 已提交
5282
         privpool->def->capacity) {
5283 5284 5285
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
5286
        goto cleanup;
C
Cole Robinson 已提交
5287 5288
    }

5289 5290
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
5291
                    privvol->name) == -1)
5292
        goto cleanup;
C
Cole Robinson 已提交
5293

5294 5295 5296
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
        VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
                                privpool->volumes.count, privvol) < 0)
5297
        goto cleanup;
C
Cole Robinson 已提交
5298

5299
    privpool->def->allocation += privvol->target.allocation;
C
Cole Robinson 已提交
5300 5301 5302
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

5303
    ret = virGetStorageVol(pool->conn, privpool->def->name,
5304 5305
                           privvol->name, privvol->key,
                           NULL, NULL);
5306
    privvol = NULL;
5307

5308
 cleanup:
5309
    virStorageVolDefFree(privvol);
5310 5311
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5312
    return ret;
C
Cole Robinson 已提交
5313 5314
}

5315
static virStorageVolPtr
5316 5317 5318 5319
testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
                            const char *xmldesc,
                            virStorageVolPtr clonevol,
                            unsigned int flags)
E
Eric Blake 已提交
5320
{
5321 5322 5323 5324 5325
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol = NULL, origvol = NULL;
    virStorageVolPtr ret = NULL;

E
Eric Blake 已提交
5326 5327
    virCheckFlags(0, NULL);

5328 5329 5330 5331 5332 5333
    testDriverLock(privconn);
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
    testDriverUnlock(privconn);

    if (privpool == NULL) {
5334
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5335 5336 5337 5338
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5339 5340
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
5341 5342 5343
        goto cleanup;
    }

5344
    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
5345 5346 5347 5348
    if (privvol == NULL)
        goto cleanup;

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
5349 5350
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
5351 5352 5353 5354 5355
        goto cleanup;
    }

    origvol = virStorageVolDefFindByName(privpool, clonevol->name);
    if (!origvol) {
5356 5357 5358
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       clonevol->name);
5359 5360 5361 5362
        goto cleanup;
    }

    /* Make sure enough space */
5363
    if ((privpool->def->allocation + privvol->target.allocation) >
5364
         privpool->def->capacity) {
5365 5366 5367
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
5368 5369 5370 5371 5372
        goto cleanup;
    }
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

5373 5374
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
5375
                    privvol->name) == -1)
5376 5377
        goto cleanup;

5378 5379 5380
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
        VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
                                privpool->volumes.count, privvol) < 0)
5381 5382
        goto cleanup;

5383
    privpool->def->allocation += privvol->target.allocation;
5384 5385 5386 5387
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    ret = virGetStorageVol(pool->conn, privpool->def->name,
5388 5389
                           privvol->name, privvol->key,
                           NULL, NULL);
5390 5391
    privvol = NULL;

5392
 cleanup:
5393 5394 5395 5396 5397 5398
    virStorageVolDefFree(privvol);
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    return ret;
}

C
Cole Robinson 已提交
5399
static int
5400 5401
testStorageVolDelete(virStorageVolPtr vol,
                     unsigned int flags)
E
Eric Blake 已提交
5402
{
5403 5404 5405
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5406
    size_t i;
5407
    int ret = -1;
C
Cole Robinson 已提交
5408

E
Eric Blake 已提交
5409 5410
    virCheckFlags(0, -1);

5411
    testDriverLock(privconn);
5412 5413
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5414
    testDriverUnlock(privconn);
5415 5416

    if (privpool == NULL) {
5417
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5418
        goto cleanup;
5419 5420 5421 5422 5423 5424
    }


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

    if (privvol == NULL) {
5425 5426 5427
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5428
        goto cleanup;
5429 5430 5431
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5432 5433
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5434
        goto cleanup;
5435 5436 5437
    }


5438
    privpool->def->allocation -= privvol->target.allocation;
C
Cole Robinson 已提交
5439 5440 5441
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

5442
    for (i = 0; i < privpool->volumes.count; i++) {
C
Cole Robinson 已提交
5443 5444 5445
        if (privpool->volumes.objs[i] == privvol) {
            virStorageVolDefFree(privvol);

5446
            VIR_DELETE_ELEMENT(privpool->volumes.objs, i, privpool->volumes.count);
C
Cole Robinson 已提交
5447 5448 5449
            break;
        }
    }
5450
    ret = 0;
C
Cole Robinson 已提交
5451

5452
 cleanup:
5453 5454
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5455
    return ret;
C
Cole Robinson 已提交
5456 5457 5458
}


5459 5460
static int testStorageVolumeTypeForPool(int pooltype)
{
C
Cole Robinson 已提交
5461

5462
    switch (pooltype) {
C
Cole Robinson 已提交
5463 5464 5465 5466 5467 5468 5469 5470 5471 5472
        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
5473
testStorageVolGetInfo(virStorageVolPtr vol,
5474 5475
                      virStorageVolInfoPtr info)
{
5476 5477 5478
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5479
    int ret = -1;
5480

5481
    testDriverLock(privconn);
5482 5483
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5484
    testDriverUnlock(privconn);
5485 5486

    if (privpool == NULL) {
5487
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5488
        goto cleanup;
5489 5490 5491 5492 5493
    }

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

    if (privvol == NULL) {
5494 5495 5496
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5497
        goto cleanup;
5498 5499 5500
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5501 5502
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5503
        goto cleanup;
5504
    }
C
Cole Robinson 已提交
5505 5506 5507

    memset(info, 0, sizeof(*info));
    info->type = testStorageVolumeTypeForPool(privpool->def->type);
5508 5509
    info->capacity = privvol->target.capacity;
    info->allocation = privvol->target.allocation;
5510
    ret = 0;
C
Cole Robinson 已提交
5511

5512
 cleanup:
5513 5514
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5515
    return ret;
C
Cole Robinson 已提交
5516 5517 5518
}

static char *
5519 5520
testStorageVolGetXMLDesc(virStorageVolPtr vol,
                         unsigned int flags)
E
Eric Blake 已提交
5521
{
5522 5523 5524
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5525
    char *ret = NULL;
5526

E
Eric Blake 已提交
5527 5528
    virCheckFlags(0, NULL);

5529
    testDriverLock(privconn);
5530 5531
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5532
    testDriverUnlock(privconn);
5533 5534

    if (privpool == NULL) {
5535
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5536
        goto cleanup;
5537 5538 5539 5540 5541
    }

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

    if (privvol == NULL) {
5542 5543 5544
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5545
        goto cleanup;
5546
    }
C
Cole Robinson 已提交
5547

5548
    if (!virStoragePoolObjIsActive(privpool)) {
5549 5550
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5551
        goto cleanup;
5552 5553
    }

5554
    ret = virStorageVolDefFormat(privpool->def, privvol);
5555

5556
 cleanup:
5557 5558
    if (privpool)
        virStoragePoolObjUnlock(privpool);
5559
    return ret;
C
Cole Robinson 已提交
5560 5561 5562
}

static char *
5563 5564
testStorageVolGetPath(virStorageVolPtr vol)
{
5565 5566 5567
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
5568
    char *ret = NULL;
5569

5570
    testDriverLock(privconn);
5571 5572
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
5573
    testDriverUnlock(privconn);
5574 5575

    if (privpool == NULL) {
5576
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
5577
        goto cleanup;
5578 5579 5580 5581 5582
    }

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

    if (privvol == NULL) {
5583 5584 5585
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vol->name);
5586
        goto cleanup;
5587 5588 5589
    }

    if (!virStoragePoolObjIsActive(privpool)) {
5590 5591
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), vol->pool);
5592
        goto cleanup;
5593 5594
    }

5595
    ignore_value(VIR_STRDUP(ret, privvol->target.path));
5596

5597
 cleanup:
5598 5599
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
5600 5601 5602
    return ret;
}

5603

5604
/* Node device implementations */
5605

5606 5607 5608
static int
testNodeNumOfDevices(virConnectPtr conn,
                     const char *cap,
E
Eric Blake 已提交
5609
                     unsigned int flags)
5610 5611 5612
{
    testConnPtr driver = conn->privateData;
    int ndevs = 0;
5613
    size_t i;
5614

E
Eric Blake 已提交
5615 5616
    virCheckFlags(0, -1);

5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631
    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 已提交
5632
                    unsigned int flags)
5633 5634 5635
{
    testConnPtr driver = conn->privateData;
    int ndevs = 0;
5636
    size_t i;
5637

E
Eric Blake 已提交
5638 5639
    virCheckFlags(0, -1);

5640 5641 5642 5643 5644
    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)) {
5645
            if (VIR_STRDUP(names[ndevs++], driver->devs.objs[i]->def->name) < 0) {
5646 5647 5648 5649 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
                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)
{
    testConnPtr driver = conn->privateData;
    virNodeDeviceObjPtr obj;
    virNodeDevicePtr ret = NULL;

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

    if (!obj) {
5676
        virReportError(VIR_ERR_NO_NODE_DEVICE, NULL);
5677 5678 5679 5680 5681
        goto cleanup;
    }

    ret = virGetNodeDevice(conn, name);

5682
 cleanup:
5683 5684 5685 5686 5687 5688
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

static char *
5689
testNodeDeviceGetXMLDesc(virNodeDevicePtr dev,
E
Eric Blake 已提交
5690
                         unsigned int flags)
5691 5692 5693 5694 5695
{
    testConnPtr driver = dev->conn->privateData;
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

E
Eric Blake 已提交
5696 5697
    virCheckFlags(0, NULL);

5698 5699 5700 5701 5702
    testDriverLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
    testDriverUnlock(driver);

    if (!obj) {
5703 5704 5705
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5706 5707 5708
        goto cleanup;
    }

5709
    ret = virNodeDeviceDefFormat(obj->def);
5710

5711
 cleanup:
5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

static char *
testNodeDeviceGetParent(virNodeDevicePtr dev)
{
    testConnPtr driver = dev->conn->privateData;
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

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

    if (!obj) {
5729 5730 5731
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5732 5733 5734 5735
        goto cleanup;
    }

    if (obj->def->parent) {
5736
        ignore_value(VIR_STRDUP(ret, obj->def->parent));
5737
    } else {
5738 5739
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no parent for this device"));
5740 5741
    }

5742
 cleanup:
5743 5744 5745 5746 5747
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

5748

5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762
static int
testNodeDeviceNumOfCaps(virNodeDevicePtr dev)
{
    testConnPtr driver = dev->conn->privateData;
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

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

    if (!obj) {
5763 5764 5765
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5766 5767 5768 5769 5770 5771 5772
        goto cleanup;
    }

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

5773
 cleanup:
5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}


static int
testNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
    testConnPtr driver = dev->conn->privateData;
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

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

    if (!obj) {
5794 5795 5796
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
5797 5798 5799 5800
        goto cleanup;
    }

    for (caps = obj->def->caps; caps && ncaps < maxnames; caps = caps->next) {
5801
        if (VIR_STRDUP(names[ncaps++], virNodeDevCapTypeToString(caps->data.type)) < 0)
5802 5803 5804 5805
            goto cleanup;
    }
    ret = ncaps;

5806
 cleanup:
5807 5808 5809 5810 5811 5812 5813 5814 5815 5816
    if (obj)
        virNodeDeviceObjUnlock(obj);
    if (ret == -1) {
        --ncaps;
        while (--ncaps >= 0)
            VIR_FREE(names[ncaps]);
    }
    return ret;
}

5817 5818 5819
static virNodeDevicePtr
testNodeDeviceCreateXML(virConnectPtr conn,
                        const char *xmlDesc,
E
Eric Blake 已提交
5820
                        unsigned int flags)
5821 5822 5823 5824 5825 5826 5827 5828 5829
{
    testConnPtr driver = conn->privateData;
    virNodeDeviceDefPtr def = NULL;
    virNodeDeviceObjPtr obj = NULL;
    char *wwnn = NULL, *wwpn = NULL;
    int parent_host = -1;
    virNodeDevicePtr dev = NULL;
    virNodeDevCapsDefPtr caps;

E
Eric Blake 已提交
5830 5831
    virCheckFlags(0, NULL);

5832 5833
    testDriverLock(driver);

5834
    def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, NULL);
5835
    if (def == NULL)
5836 5837 5838
        goto cleanup;

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

5842
    if (virNodeDeviceGetParentHost(&driver->devs,
5843 5844 5845 5846 5847 5848 5849 5850 5851
                                   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);
5852
    if (VIR_STRDUP(def->name, wwpn) < 0)
5853 5854
        goto cleanup;

J
John Ferlan 已提交
5855 5856
    /* Fill in a random 'host' and 'unique_id' value,
     * since this would also come from the backend */
5857 5858
    caps = def->caps;
    while (caps) {
5859
        if (caps->data.type != VIR_NODE_DEV_CAP_SCSI_HOST)
5860 5861
            continue;

5862
        caps->data.scsi_host.host = virRandomBits(10);
J
John Ferlan 已提交
5863
        caps->data.scsi_host.unique_id = 2;
5864 5865 5866 5867
        caps = caps->next;
    }


5868
    if (!(obj = virNodeDeviceAssignDef(&driver->devs, def)))
5869 5870 5871 5872 5873
        goto cleanup;
    virNodeDeviceObjUnlock(obj);

    dev = virGetNodeDevice(conn, def->name);
    def = NULL;
5874
 cleanup:
5875
    testDriverUnlock(driver);
5876
    virNodeDeviceDefFree(def);
5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return dev;
}

static int
testNodeDeviceDestroy(virNodeDevicePtr dev)
{
    int ret = 0;
    testConnPtr driver = dev->conn->privateData;
    virNodeDeviceObjPtr obj = NULL;
    char *parent_name = NULL, *wwnn = NULL, *wwpn = NULL;
    int parent_host = -1;

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

    if (!obj) {
5896
        virReportError(VIR_ERR_NO_NODE_DEVICE, NULL);
5897 5898 5899
        goto out;
    }

5900
    if (virNodeDeviceGetWWNs(obj->def, &wwnn, &wwpn) == -1)
5901 5902
        goto out;

5903
    if (VIR_STRDUP(parent_name, obj->def->parent) < 0)
5904 5905 5906 5907 5908 5909 5910 5911 5912
        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 */
5913
    if (virNodeDeviceGetParentHost(&driver->devs,
5914 5915 5916 5917 5918 5919 5920 5921 5922 5923
                                   dev->name,
                                   parent_name,
                                   &parent_host) == -1) {
        obj = NULL;
        goto out;
    }

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

5924
 out:
5925 5926 5927 5928 5929 5930 5931 5932
    if (obj)
        virNodeDeviceObjUnlock(obj);
    VIR_FREE(parent_name);
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return ret;
}

5933 5934

/* Domain event implementations */
5935
static int
5936 5937 5938 5939
testConnectDomainEventRegister(virConnectPtr conn,
                               virConnectDomainEventCallback callback,
                               void *opaque,
                               virFreeCallback freecb)
5940 5941
{
    testConnPtr driver = conn->privateData;
5942
    int ret = 0;
5943 5944

    testDriverLock(driver);
5945
    if (virDomainEventStateRegister(conn, driver->eventState,
5946 5947
                                    callback, opaque, freecb) < 0)
        ret = -1;
5948 5949 5950 5951 5952
    testDriverUnlock(driver);

    return ret;
}

5953

5954
static int
5955 5956
testConnectDomainEventDeregister(virConnectPtr conn,
                                 virConnectDomainEventCallback callback)
5957 5958
{
    testConnPtr driver = conn->privateData;
5959
    int ret = 0;
5960 5961

    testDriverLock(driver);
5962
    if (virDomainEventStateDeregister(conn, driver->eventState,
5963 5964
                                      callback) < 0)
        ret = -1;
5965 5966 5967 5968 5969
    testDriverUnlock(driver);

    return ret;
}

5970 5971

static int
5972 5973 5974 5975 5976 5977
testConnectDomainEventRegisterAny(virConnectPtr conn,
                                  virDomainPtr dom,
                                  int eventID,
                                  virConnectDomainEventGenericCallback callback,
                                  void *opaque,
                                  virFreeCallback freecb)
5978 5979 5980 5981 5982
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
5983
    if (virDomainEventStateRegisterID(conn, driver->eventState,
5984 5985
                                      dom, eventID,
                                      callback, opaque, freecb, &ret) < 0)
5986
        ret = -1;
5987 5988 5989 5990 5991 5992
    testDriverUnlock(driver);

    return ret;
}

static int
5993 5994
testConnectDomainEventDeregisterAny(virConnectPtr conn,
                                    int callbackID)
5995 5996
{
    testConnPtr driver = conn->privateData;
5997
    int ret = 0;
5998 5999

    testDriverLock(driver);
6000
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
6001 6002
                                        callbackID) < 0)
        ret = -1;
6003 6004 6005 6006 6007 6008
    testDriverUnlock(driver);

    return ret;
}


6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020
static int
testConnectNetworkEventRegisterAny(virConnectPtr conn,
                                   virNetworkPtr net,
                                   int eventID,
                                   virConnectNetworkEventGenericCallback callback,
                                   void *opaque,
                                   virFreeCallback freecb)
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
6021
    if (virNetworkEventStateRegisterID(conn, driver->eventState,
6022
                                       net, eventID, callback,
6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034
                                       opaque, freecb, &ret) < 0)
        ret = -1;
    testDriverUnlock(driver);

    return ret;
}

static int
testConnectNetworkEventDeregisterAny(virConnectPtr conn,
                                     int callbackID)
{
    testConnPtr driver = conn->privateData;
6035
    int ret = 0;
6036 6037

    testDriverLock(driver);
6038
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
6039 6040
                                        callbackID) < 0)
        ret = -1;
6041 6042 6043 6044 6045 6046
    testDriverUnlock(driver);

    return ret;
}


6047
/* driver must be locked before calling */
6048
static void testObjectEventQueue(testConnPtr driver,
6049
                                 virObjectEventPtr event)
6050
{
6051
    virObjectEventStateQueue(driver->eventState, event);
6052 6053
}

6054

6055 6056 6057
static int testConnectListAllDomains(virConnectPtr conn,
                                     virDomainPtr **domains,
                                     unsigned int flags)
6058 6059 6060 6061
{
    testConnPtr privconn = conn->privateData;
    int ret;

O
Osier Yang 已提交
6062
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
6063 6064

    testDriverLock(privconn);
6065 6066
    ret = virDomainObjListExport(privconn->domains, conn, domains,
                                 NULL, flags);
6067 6068 6069 6070 6071
    testDriverUnlock(privconn);

    return ret;
}

6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084
static int
testNodeGetCPUMap(virConnectPtr conn,
                  unsigned char **cpumap,
                  unsigned int *online,
                  unsigned int flags)
{
    testConnPtr privconn = conn->privateData;
    int ret = -1;

    virCheckFlags(0, -1);

    testDriverLock(privconn);
    if (cpumap) {
6085
        if (VIR_ALLOC_N(*cpumap, 1) < 0)
6086 6087 6088 6089 6090 6091 6092 6093 6094
            goto cleanup;
        *cpumap[0] = 0x15;
    }

    if (online)
        *online = 3;

    ret = 8;

6095
 cleanup:
6096 6097 6098 6099
    testDriverUnlock(privconn);
    return ret;
}

6100 6101 6102 6103 6104 6105 6106 6107 6108 6109
static char *
testDomainScreenshot(virDomainPtr dom ATTRIBUTE_UNUSED,
                     virStreamPtr st,
                     unsigned int screen ATTRIBUTE_UNUSED,
                     unsigned int flags)
{
    char *ret = NULL;

    virCheckFlags(0, NULL);

6110
    if (VIR_STRDUP(ret, "image/png") < 0)
6111 6112
        return NULL;

6113
    if (virFDStreamOpenFile(st, PKGDATADIR "/libvirtLogo.png", 0, 0, O_RDONLY) < 0)
6114 6115 6116 6117 6118
        VIR_FREE(ret);

    return ret;
}

6119 6120 6121 6122 6123 6124 6125 6126 6127
static int
testConnectGetCPUModelNames(virConnectPtr conn ATTRIBUTE_UNUSED,
                            const char *arch,
                            char ***models,
                            unsigned int flags)
{
    virCheckFlags(0, -1);
    return cpuGetModels(arch, models);
}
6128

C
Cole Robinson 已提交
6129 6130 6131 6132 6133
static int
testDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
    testConnPtr privconn = dom->conn->privateData;
    virDomainObjPtr vm = NULL;
6134
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162
    int ret = -1;

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

    testDriverLock(privconn);
    vm = virDomainObjListFindByName(privconn->domains, dom->name);
    testDriverUnlock(privconn);

    if (vm == NULL) {
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
        goto cleanup;
    }

    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);
6163
    event = virDomainEventLifecycleNewFromObj(vm,
C
Cole Robinson 已提交
6164 6165 6166 6167 6168
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
    vm->hasManagedSave = true;

    ret = 0;
6169
 cleanup:
6170
    virDomainObjEndAPI(&vm);
C
Cole Robinson 已提交
6171 6172
    if (event) {
        testDriverLock(privconn);
6173
        testObjectEventQueue(privconn, event);
C
Cole Robinson 已提交
6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198
        testDriverUnlock(privconn);
    }

    return ret;
}


static int
testDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    testConnPtr privconn = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(0, -1);

    testDriverLock(privconn);

    vm = virDomainObjListFindByName(privconn->domains, dom->name);
    if (vm == NULL) {
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
        goto cleanup;
    }

    ret = vm->hasManagedSave;
6199
 cleanup:
6200
    virDomainObjEndAPI(&vm);
C
Cole Robinson 已提交
6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223
    testDriverUnlock(privconn);
    return ret;
}

static int
testDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
{
    testConnPtr privconn = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(0, -1);

    testDriverLock(privconn);

    vm = virDomainObjListFindByName(privconn->domains, dom->name);
    if (vm == NULL) {
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
        goto cleanup;
    }

    vm->hasManagedSave = false;
    ret = 0;
6224
 cleanup:
6225
    virDomainObjEndAPI(&vm);
C
Cole Robinson 已提交
6226 6227 6228 6229 6230
    testDriverUnlock(privconn);
    return ret;
}


6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274
/*
 * 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;
    int n = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
        goto cleanup;

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

6275
 cleanup:
6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298
    if (vm)
        virObjectUnlock(vm);
    return n;
}

static int
testDomainSnapshotListNames(virDomainPtr domain,
                            char **names,
                            int nameslen,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int n = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
        goto cleanup;

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

6299
 cleanup:
6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320
    if (vm)
        virObjectUnlock(vm);
    return n;
}

static int
testDomainListAllSnapshots(virDomainPtr domain,
                           virDomainSnapshotPtr **snaps,
                           unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int n = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
        goto cleanup;

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

6321
 cleanup:
6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348
    if (vm)
        virObjectUnlock(vm);
    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)))
        goto cleanup;

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

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

6349
 cleanup:
6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373
    if (vm)
        virObjectUnlock(vm);
    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)))
        goto cleanup;

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

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

6374
 cleanup:
6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400
    if (vm)
        virObjectUnlock(vm);
    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)))
        goto cleanup;

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

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

6401
 cleanup:
6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425
    if (vm)
        virObjectUnlock(vm);
    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)))
        goto cleanup;

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

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

6426
 cleanup:
6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445
    if (vm)
        virObjectUnlock(vm);
    return snapshot;
}

static int
testDomainHasCurrentSnapshot(virDomainPtr domain,
                             unsigned int flags)
{
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(domain)))
        goto cleanup;

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

6446
 cleanup:
6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476
    if (vm)
        virObjectUnlock(vm);
    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)))
        goto cleanup;

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

6477
 cleanup:
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
    if (vm)
        virObjectUnlock(vm);
    return parent;
}

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

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
        goto cleanup;

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

6503
 cleanup:
6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527
    if (vm)
        virObjectUnlock(vm);
    return snapshot;
}

static char *
testDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
                             unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    char *xml = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    char uuidstr[VIR_UUID_STRING_BUFLEN];

    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
        goto cleanup;

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

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

6528 6529 6530
    xml = virDomainSnapshotDefFormat(uuidstr, snap->def,
                                     virDomainDefFormatConvertXMLFlags(flags),
                                     0);
6531

6532
 cleanup:
6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552
    if (vm)
        virObjectUnlock(vm);
    return xml;
}

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

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
        goto cleanup;

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

6553
 cleanup:
6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571
    if (vm)
        virObjectUnlock(vm);
    return ret;
}


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

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
        goto cleanup;

C
Cole Robinson 已提交
6572
    if (!testSnapObjFromSnapshot(vm, snapshot))
6573 6574 6575 6576
        goto cleanup;

    ret = 1;

6577
 cleanup:
6578 6579 6580 6581 6582
    if (vm)
        virObjectUnlock(vm);
    return ret;
}

6583 6584 6585 6586 6587 6588
static int
testDomainSnapshotAlignDisks(virDomainObjPtr vm,
                             virDomainSnapshotDefPtr def,
                             unsigned int flags)
{
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
E
Eric Blake 已提交
6589
    bool align_match = true;
6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622

    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)
{
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr vm = NULL;
    virDomainSnapshotDefPtr def = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr snapshot = NULL;
6623
    virObjectEventPtr event = NULL;
6624
    char *xml = NULL;
6625 6626
    bool update_current = true;
    bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
6627 6628 6629 6630 6631 6632 6633 6634
    unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;

    /*
     * DISK_ONLY: Not implemented yet
     * REUSE_EXT: Not implemented yet
     *
     * NO_METADATA: Explicitly not implemented
     *
6635
     * REDEFINE + CURRENT: Implemented
6636 6637 6638 6639 6640 6641
     * HALT: Implemented
     * QUIESCE: Nothing to do
     * ATOMIC: Nothing to do
     * LIVE: Nothing to do
     */
    virCheckFlags(
6642 6643
        VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
        VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
6644 6645 6646 6647 6648
        VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
        VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
        VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
        VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, NULL);

6649 6650 6651 6652 6653
    if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)))
        update_current = false;
    if (redefine)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;

6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668
    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;

6669
    if (redefine) {
C
Cole Robinson 已提交
6670 6671
        if (virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
                                          &update_current, flags) < 0)
6672 6673 6674 6675 6676 6677 6678
            goto cleanup;
    } else {
        if (!(def->dom = virDomainDefCopy(vm->def,
                                          privconn->caps,
                                          privconn->xmlopt,
                                          true)))
            goto cleanup;
6679

6680
        if (testDomainSnapshotAlignDisks(vm, def, flags) < 0)
6681 6682 6683
            goto cleanup;
    }

6684 6685 6686 6687
    if (!snap) {
        if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
            goto cleanup;
        def = NULL;
6688 6689
    }

6690 6691 6692 6693 6694 6695 6696 6697 6698 6699
    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);
6700
            event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
6701 6702 6703
                                    VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
        }
    }
6704 6705

    snapshot = virGetDomainSnapshot(domain, snap->def->name);
6706
 cleanup:
6707 6708 6709 6710
    VIR_FREE(xml);
    if (vm) {
        if (snapshot) {
            virDomainSnapshotObjPtr other;
6711 6712
            if (update_current)
                vm->current_snapshot = snap;
6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723
            other = virDomainSnapshotFindByName(vm->snapshots,
                                                snap->def->parent);
            snap->parent = other;
            other->nchildren++;
            snap->sibling = other->first_child;
            other->first_child = snap;
        }
        virObjectUnlock(vm);
    }
    if (event) {
        testDriverLock(privconn);
6724
        testObjectEventQueue(privconn, event);
6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768
        testDriverUnlock(privconn);
    }
    virDomainSnapshotDefFree(def);
    return snapshot;
}


typedef struct _testSnapRemoveData testSnapRemoveData;
typedef testSnapRemoveData *testSnapRemoveDataPtr;
struct _testSnapRemoveData {
    virDomainObjPtr vm;
    bool current;
};

static void
testDomainSnapshotDiscardAll(void *payload,
                          const void *name ATTRIBUTE_UNUSED,
                          void *data)
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapRemoveDataPtr curr = data;

    if (snap->def->current)
        curr->current = true;
    virDomainSnapshotObjListRemove(curr->vm->snapshots, snap);
}

typedef struct _testSnapReparentData testSnapReparentData;
typedef testSnapReparentData *testSnapReparentDataPtr;
struct _testSnapReparentData {
    virDomainSnapshotObjPtr parent;
    virDomainObjPtr vm;
    int err;
    virDomainSnapshotObjPtr last;
};

static void
testDomainSnapshotReparentChildren(void *payload,
                                   const void *name ATTRIBUTE_UNUSED,
                                   void *data)
{
    virDomainSnapshotObjPtr snap = payload;
    testSnapReparentDataPtr rep = data;

6769
    if (rep->err < 0)
6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811
        return;

    VIR_FREE(snap->def->parent);
    snap->parent = rep->parent;

    if (rep->parent->def &&
        VIR_STRDUP(snap->def->parent, rep->parent->def->name) < 0) {
        rep->err = -1;
        return;
    }

    if (!snap->sibling)
        rep->last = snap;
}

static int
testDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
                         unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotObjPtr parentsnap = NULL;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
                  VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY, -1);

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

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

    if (flags & (VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
                 VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)) {
        testSnapRemoveData rem;
        rem.vm = vm;
        rem.current = false;
        virDomainSnapshotForEachDescendant(snap,
                                           testDomainSnapshotDiscardAll,
                                           &rem);
        if (rem.current) {
6812
            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)
6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855
                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;
6856
 cleanup:
6857 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868
    if (vm)
        virObjectUnlock(vm);
    return ret;
}

static int
testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                           unsigned int flags)
{
    testConnPtr privconn = snapshot->domain->conn->privateData;
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
6869 6870
    virObjectEventPtr event = NULL;
    virObjectEventPtr event2 = NULL;
6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962 6963
    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;

    testDriverLock(privconn);

    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);
6964
                event = virDomainEventLifecycleNewFromObj(vm,
6965 6966 6967
                            VIR_DOMAIN_EVENT_STOPPED,
                            VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
                if (event)
6968
                    testObjectEventQueue(privconn, event);
6969 6970 6971 6972 6973 6974 6975 6976 6977 6978 6979
                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. */
6980
                event = virDomainEventLifecycleNewFromObj(vm,
6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993
                                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;
6994
            event = virDomainEventLifecycleNewFromObj(vm,
6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007
                                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 */
7008
                event2 = virDomainEventLifecycleNewFromObj(vm,
7009 7010 7011 7012 7013
                                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 已提交
7014
            virObjectUnref(event);
7015 7016 7017 7018
            event = NULL;

            if (was_stopped) {
                /* Transition 2 */
7019
                event = virDomainEventLifecycleNewFromObj(vm,
7020 7021 7022 7023
                                VIR_DOMAIN_EVENT_STARTED,
                                VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            } else if (was_running) {
                /* Transition 8 */
7024
                event = virDomainEventLifecycleNewFromObj(vm,
7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036
                                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);
7037
            event = virDomainEventLifecycleNewFromObj(vm,
7038 7039 7040 7041 7042 7043 7044 7045 7046 7047
                                    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;

            if (event)
7048
                testObjectEventQueue(privconn, event);
7049
            event = virDomainEventLifecycleNewFromObj(vm,
7050 7051 7052
                            VIR_DOMAIN_EVENT_STARTED,
                            VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            if (paused) {
7053
                event2 = virDomainEventLifecycleNewFromObj(vm,
7054 7055 7056 7057 7058 7059 7060 7061
                                VIR_DOMAIN_EVENT_SUSPENDED,
                                VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
            }
        }
    }

    vm->current_snapshot = snap;
    ret = 0;
7062
 cleanup:
7063
    if (event) {
7064
        testObjectEventQueue(privconn, event);
7065
        if (event2)
7066
            testObjectEventQueue(privconn, event2);
C
Cole Robinson 已提交
7067
    } else {
C
Cédric Bosdonnat 已提交
7068
        virObjectUnref(event2);
7069 7070 7071 7072 7073 7074 7075 7076
    }
    virObjectUnlock(vm);
    testDriverUnlock(privconn);

    return ret;
}


7077

7078
static virHypervisorDriver testHypervisorDriver = {
7079
    .name = "Test",
7080 7081 7082
    .connectOpen = testConnectOpen, /* 0.1.1 */
    .connectClose = testConnectClose, /* 0.1.1 */
    .connectGetVersion = testConnectGetVersion, /* 0.1.1 */
7083
    .connectGetHostname = testConnectGetHostname, /* 0.6.3 */
7084
    .connectGetMaxVcpus = testConnectGetMaxVcpus, /* 0.3.2 */
7085
    .nodeGetInfo = testNodeGetInfo, /* 0.1.1 */
7086 7087 7088 7089
    .connectGetCapabilities = testConnectGetCapabilities, /* 0.2.1 */
    .connectListDomains = testConnectListDomains, /* 0.1.1 */
    .connectNumOfDomains = testConnectNumOfDomains, /* 0.1.1 */
    .connectListAllDomains = testConnectListAllDomains, /* 0.9.13 */
7090
    .domainCreateXML = testDomainCreateXML, /* 0.1.4 */
7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104
    .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 */
7105 7106
    .domainGetState = testDomainGetState, /* 0.9.2 */
    .domainSave = testDomainSave, /* 0.3.2 */
7107
    .domainSaveFlags = testDomainSaveFlags, /* 0.9.4 */
7108
    .domainRestore = testDomainRestore, /* 0.3.2 */
7109
    .domainRestoreFlags = testDomainRestoreFlags, /* 0.9.4 */
7110
    .domainCoreDump = testDomainCoreDump, /* 0.3.2 */
7111
    .domainCoreDumpWithFormat = testDomainCoreDumpWithFormat, /* 1.2.3 */
7112
    .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */
7113 7114 7115 7116 7117 7118
    .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */
    .domainGetVcpusFlags = testDomainGetVcpusFlags, /* 0.8.5 */
    .domainPinVcpu = testDomainPinVcpu, /* 0.7.3 */
    .domainGetVcpus = testDomainGetVcpus, /* 0.7.3 */
    .domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
    .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
7119 7120
    .connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
    .connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
7121 7122 7123
    .domainCreate = testDomainCreate, /* 0.1.11 */
    .domainCreateWithFlags = testDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = testDomainDefineXML, /* 0.1.11 */
7124
    .domainDefineXMLFlags = testDomainDefineXMLFlags, /* 1.2.12 */
7125
    .domainUndefine = testDomainUndefine, /* 0.1.11 */
7126
    .domainUndefineFlags = testDomainUndefineFlags, /* 0.9.4 */
7127 7128 7129
    .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
    .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
    .domainGetSchedulerType = testDomainGetSchedulerType, /* 0.3.2 */
7130 7131 7132 7133
    .domainGetSchedulerParameters = testDomainGetSchedulerParameters, /* 0.3.2 */
    .domainGetSchedulerParametersFlags = testDomainGetSchedulerParametersFlags, /* 0.9.2 */
    .domainSetSchedulerParameters = testDomainSetSchedulerParameters, /* 0.3.2 */
    .domainSetSchedulerParametersFlags = testDomainSetSchedulerParametersFlags, /* 0.9.2 */
7134 7135 7136
    .domainBlockStats = testDomainBlockStats, /* 0.7.0 */
    .domainInterfaceStats = testDomainInterfaceStats, /* 0.7.0 */
    .nodeGetCellsFreeMemory = testNodeGetCellsFreeMemory, /* 0.4.2 */
7137 7138 7139 7140
    .connectDomainEventRegister = testConnectDomainEventRegister, /* 0.6.0 */
    .connectDomainEventDeregister = testConnectDomainEventDeregister, /* 0.6.0 */
    .connectIsEncrypted = testConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = testConnectIsSecure, /* 0.7.3 */
7141 7142 7143
    .domainIsActive = testDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = testDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = testDomainIsUpdated, /* 0.8.6 */
7144 7145 7146
    .connectDomainEventRegisterAny = testConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = testConnectDomainEventDeregisterAny, /* 0.8.0 */
    .connectIsAlive = testConnectIsAlive, /* 0.9.8 */
7147
    .nodeGetCPUMap = testNodeGetCPUMap, /* 1.0.0 */
7148
    .domainScreenshot = testDomainScreenshot, /* 1.0.5 */
7149 7150
    .domainGetMetadata = testDomainGetMetadata, /* 1.1.3 */
    .domainSetMetadata = testDomainSetMetadata, /* 1.1.3 */
7151
    .connectGetCPUModelNames = testConnectGetCPUModelNames, /* 1.1.3 */
7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168
    .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 */
7169 7170 7171
    .domainSnapshotCreateXML = testDomainSnapshotCreateXML, /* 1.1.4 */
    .domainRevertToSnapshot = testDomainRevertToSnapshot, /* 1.1.4 */
    .domainSnapshotDelete = testDomainSnapshotDelete, /* 1.1.4 */
7172

E
Eric Blake 已提交
7173
    .connectBaselineCPU = testConnectBaselineCPU, /* 1.2.0 */
7174 7175 7176
};

static virNetworkDriver testNetworkDriver = {
7177 7178 7179 7180 7181
    .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 */
7182 7183
    .connectNetworkEventRegisterAny = testConnectNetworkEventRegisterAny, /* 1.2.1 */
    .connectNetworkEventDeregisterAny = testConnectNetworkEventDeregisterAny, /* 1.2.1 */
7184 7185 7186 7187
    .networkLookupByUUID = testNetworkLookupByUUID, /* 0.3.2 */
    .networkLookupByName = testNetworkLookupByName, /* 0.3.2 */
    .networkCreateXML = testNetworkCreateXML, /* 0.3.2 */
    .networkDefineXML = testNetworkDefineXML, /* 0.3.2 */
7188
    .networkUndefine = testNetworkUndefine, /* 0.3.2 */
7189
    .networkUpdate = testNetworkUpdate, /* 0.10.2 */
7190
    .networkCreate = testNetworkCreate, /* 0.3.2 */
7191 7192 7193 7194 7195 7196 7197
    .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 */
7198 7199
};

L
Laine Stump 已提交
7200
static virInterfaceDriver testInterfaceDriver = {
7201 7202 7203 7204 7205 7206
    .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 */
7207 7208 7209 7210 7211 7212
    .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 */
7213 7214 7215
    .interfaceChangeBegin = testInterfaceChangeBegin,   /* 0.9.2 */
    .interfaceChangeCommit = testInterfaceChangeCommit,  /* 0.9.2 */
    .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */
L
Laine Stump 已提交
7216 7217 7218
};


7219
static virStorageDriver testStorageDriver = {
7220 7221 7222 7223 7224 7225
    .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 */
7226 7227 7228
    .storagePoolLookupByName = testStoragePoolLookupByName, /* 0.5.0 */
    .storagePoolLookupByUUID = testStoragePoolLookupByUUID, /* 0.5.0 */
    .storagePoolLookupByVolume = testStoragePoolLookupByVolume, /* 0.5.0 */
7229 7230
    .storagePoolCreateXML = testStoragePoolCreateXML, /* 0.5.0 */
    .storagePoolDefineXML = testStoragePoolDefineXML, /* 0.5.0 */
7231 7232
    .storagePoolBuild = testStoragePoolBuild, /* 0.5.0 */
    .storagePoolUndefine = testStoragePoolUndefine, /* 0.5.0 */
7233
    .storagePoolCreate = testStoragePoolCreate, /* 0.5.0 */
7234 7235 7236 7237 7238 7239 7240
    .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 */
7241
    .storagePoolNumOfVolumes = testStoragePoolNumOfVolumes, /* 0.5.0 */
7242 7243 7244
    .storagePoolListVolumes = testStoragePoolListVolumes, /* 0.5.0 */
    .storagePoolListAllVolumes = testStoragePoolListAllVolumes, /* 0.10.2 */

7245 7246 7247 7248 7249 7250 7251 7252 7253
    .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 */
7254 7255
    .storagePoolIsActive = testStoragePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = testStoragePoolIsPersistent, /* 0.7.3 */
7256 7257
};

7258
static virNodeDeviceDriver testNodeDeviceDriver = {
7259 7260 7261 7262 7263 7264 7265 7266 7267
    .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 */
7268 7269
};

7270 7271 7272 7273 7274 7275 7276 7277
static virConnectDriver testConnectDriver = {
    .hypervisorDriver = &testHypervisorDriver,
    .interfaceDriver = &testInterfaceDriver,
    .networkDriver = &testNetworkDriver,
    .nodeDeviceDriver = &testNodeDeviceDriver,
    .nwfilterDriver = NULL,
    .secretDriver = NULL,
    .storageDriver = &testStorageDriver,
7278 7279
};

7280 7281 7282 7283 7284 7285 7286 7287
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
7288 7289
    return virRegisterConnectDriver(&testConnectDriver,
                                    false);
7290
}