test_driver.c 222.3 KB
Newer Older
1
/*
2
 * test_driver.c: A "mock" hypervisor for use by application unit tests
3
 *
4
 * Copyright (C) 2006-2019 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
#include <config.h>
23

24
#include <sys/time.h>
25 26
#include <fcntl.h>
#include <unistd.h>
27
#include <sys/stat.h>
C
Cole Robinson 已提交
28
#include <libxml/xmlsave.h>
29
#include <libxml/xpathInternals.h>
30

31

32
#include "virerror.h"
33
#include "datatypes.h"
34
#include "test_driver.h"
35
#include "virbuffer.h"
36
#include "viruuid.h"
37
#include "capabilities.h"
38
#include "configmake.h"
39
#include "viralloc.h"
J
John Ferlan 已提交
40
#include "virnetworkobj.h"
L
Laine Stump 已提交
41
#include "interface_conf.h"
42
#include "domain_conf.h"
43
#include "domain_event.h"
44
#include "network_event.h"
45
#include "snapshot_conf.h"
46
#include "virfdstream.h"
C
Cole Robinson 已提交
47
#include "storage_conf.h"
J
John Ferlan 已提交
48
#include "virstorageobj.h"
49
#include "storage_event.h"
50
#include "node_device_conf.h"
J
John Ferlan 已提交
51
#include "virnodedeviceobj.h"
52
#include "node_device_event.h"
53
#include "virxml.h"
54
#include "virthread.h"
55
#include "virlog.h"
E
Eric Blake 已提交
56
#include "virfile.h"
57
#include "virtypedparam.h"
58
#include "virrandom.h"
59
#include "virstring.h"
60
#include "cpu/cpu.h"
61
#include "virauth.h"
62
#include "viratomic.h"
63
#include "virdomainobjlist.h"
J
John Ferlan 已提交
64
#include "virinterfaceobj.h"
65
#include "virhostcpu.h"
66
#include "virdomainsnapshotobjlist.h"
67
#include "virkeycode.h"
68

69 70
#define VIR_FROM_THIS VIR_FROM_TEST

71 72
VIR_LOG_INIT("test.test_driver");

73

74 75 76 77
#define MAX_CPUS 128

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

#define MAX_CELLS 128
86

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

94
struct _testDriver {
95
    virObjectLockable parent;
96

97
    virNodeInfo nodeInfo;
98
    virInterfaceObjListPtr ifaces;
99
    bool transaction_running;
100
    virInterfaceObjListPtr backupIfaces;
101
    virStoragePoolObjListPtr pools;
102
    virNodeDeviceObjListPtr devs;
103 104
    int numCells;
    testCell cells[MAX_CELLS];
105 106
    size_t numAuths;
    testAuthPtr auths;
107

108 109 110
    /* virAtomic access only */
    volatile int nextDomID;

111 112 113 114 115 116 117 118 119 120
    /* immutable pointer, immutable object after being initialized with
     * testBuildCapabilities */
    virCapsPtr caps;

    /* immutable pointer, immutable object */
    virDomainXMLOptionPtr xmlopt;

    /* immutable pointer, self-locking APIs */
    virDomainObjListPtr domains;
    virNetworkObjListPtr networks;
121
    virObjectEventStatePtr eventState;
122
};
123 124
typedef struct _testDriver testDriver;
typedef testDriver *testDriverPtr;
125

126
static testDriverPtr defaultPrivconn;
127
static virMutex defaultLock = VIR_MUTEX_INITIALIZER;
128

129 130 131 132 133 134 135 136 137
static virClassPtr testDriverClass;
static void testDriverDispose(void *obj);
static int testDriverOnceInit(void)
{
    if (!(VIR_CLASS_NEW(testDriver, virClassForObjectLockable())))
        return -1;

    return 0;
}
138
VIR_ONCE_GLOBAL_INIT(testDriver);
139

140
#define TEST_MODEL "i686"
141
#define TEST_EMULATOR "/usr/bin/test-hv"
142

143
static const virNodeInfo defaultNodeInfo = {
144
    TEST_MODEL,
145 146 147 148 149 150 151
    1024*1024*3, /* 3 GB */
    16,
    1400,
    2,
    2,
    2,
    2,
152 153
};

154
static void
155
testDriverDispose(void *obj)
156
{
157
    testDriverPtr driver = obj;
158 159 160 161

    virObjectUnref(driver->caps);
    virObjectUnref(driver->xmlopt);
    virObjectUnref(driver->domains);
162
    virNodeDeviceObjListFree(driver->devs);
163
    virObjectUnref(driver->networks);
164
    virObjectUnref(driver->ifaces);
165
    virObjectUnref(driver->pools);
166
    virObjectUnref(driver->eventState);
167 168
}

169 170 171 172 173 174
#define TEST_NAMESPACE_HREF "http://libvirt.org/schemas/domain/test/1.0"

typedef struct _testDomainNamespaceDef testDomainNamespaceDef;
typedef testDomainNamespaceDef *testDomainNamespaceDefPtr;
struct _testDomainNamespaceDef {
    int runstate;
175
    bool transient;
C
Cole Robinson 已提交
176
    bool hasManagedSave;
177 178 179

    unsigned int num_snap_nodes;
    xmlNodePtr *snap_nodes;
180 181 182 183 184 185
};

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

static int
testDomainDefNamespaceParse(xmlDocPtr xml ATTRIBUTE_UNUSED,
                            xmlNodePtr root ATTRIBUTE_UNUSED,
                            xmlXPathContextPtr ctxt,
                            void **data)
{
    testDomainNamespaceDefPtr nsdata = NULL;
205 206
    int tmp, n;
    size_t i;
207
    unsigned int tmpuint;
208
    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
209 210 211 212 213 214 215 216 217 218 219 220

    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;

221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
    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++;
    }

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

253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
    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;
    }

269 270 271 272 273
    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 已提交
274 275 276 277 278
    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;
    }
279

280 281 282
    *data = nsdata;
    return 0;

283
 error:
284 285 286
    testDomainDefNamespaceFree(nsdata);
    return -1;
}
287

288
static virCapsPtr
289 290
testBuildCapabilities(virConnectPtr conn)
{
291
    testDriverPtr privconn = conn->privateData;
292 293
    virCapsPtr caps;
    virCapsGuestPtr guest;
294 295
    int guest_types[] = { VIR_DOMAIN_OSTYPE_HVM,
                          VIR_DOMAIN_OSTYPE_XEN };
296
    size_t i, j;
297

298
    if ((caps = virCapabilitiesNew(VIR_ARCH_I686, false, false)) == NULL)
299
        goto error;
300

301
    if (virCapabilitiesAddHostFeature(caps, "pae") < 0)
302
        goto error;
303
    if (virCapabilitiesAddHostFeature(caps, "nonpae") < 0)
304
        goto error;
305

306 307
    virCapabilitiesHostInitIOMMU(caps);

308
    if (VIR_ALLOC_N(caps->host.pagesSize, 4) < 0)
309 310 311
        goto error;

    caps->host.pagesSize[caps->host.nPagesSize++] = 4;
312
    caps->host.pagesSize[caps->host.nPagesSize++] = 8;
313
    caps->host.pagesSize[caps->host.nPagesSize++] = 2048;
314
    caps->host.pagesSize[caps->host.nPagesSize++] = 1024 * 1024;
315

316
    for (i = 0; i < privconn->numCells; i++) {
317
        virCapsHostNUMACellCPUPtr cpu_cells;
318
        virCapsHostNUMACellPageInfoPtr pages;
319
        size_t nPages = caps->host.nPagesSize - 1;
320

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

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

330 331 332 333 334 335 336
        if (i == 1)
            pages[0].size = caps->host.pagesSize[1];
        else
            pages[0].size = caps->host.pagesSize[0];

        for (j = 1; j < nPages; j++)
            pages[j].size = caps->host.pagesSize[j + 1];
337 338

        pages[0].avail = privconn->cells[i].mem / pages[0].size;
339

340
        if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].mem,
341
                                           privconn->cells[i].numCpus,
342
                                           cpu_cells, 0, NULL, nPages, pages) < 0)
343
            goto error;
344 345
    }

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

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

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

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

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

379
    return caps;
380

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

386

387 388 389 390 391 392 393
static testDriverPtr
testDriverNew(void)
{
    virDomainXMLNamespace ns = {
        .parse = testDomainDefNamespaceParse,
        .free = testDomainDefNamespaceFree,
    };
394 395 396 397 398 399 400 401
    virDomainDefParserConfig config = {
        .features = VIR_DOMAIN_DEF_FEATURE_MEMORY_HOTPLUG |
                    VIR_DOMAIN_DEF_FEATURE_OFFLINE_VCPUPIN |
                    VIR_DOMAIN_DEF_FEATURE_INDIVIDUAL_VCPUS |
                    VIR_DOMAIN_DEF_FEATURE_USER_ALIAS |
                    VIR_DOMAIN_DEF_FEATURE_FW_AUTOSELECT |
                    VIR_DOMAIN_DEF_FEATURE_NET_MODEL_STRING,
    };
402 403
    testDriverPtr ret;

404
    if (testDriverInitialize() < 0)
405 406
        return NULL;

407 408
    if (!(ret = virObjectLockableNew(testDriverClass)))
        return NULL;
409

410
    if (!(ret->xmlopt = virDomainXMLOptionNew(&config, NULL, &ns, NULL, NULL)) ||
411
        !(ret->eventState = virObjectEventStateNew()) ||
412
        !(ret->ifaces = virInterfaceObjListNew()) ||
413
        !(ret->domains = virDomainObjListNew()) ||
414
        !(ret->networks = virNetworkObjListNew()) ||
415 416
        !(ret->devs = virNodeDeviceObjListNew()) ||
        !(ret->pools = virStoragePoolObjListNew()))
417 418
        goto error;

419
    virAtomicIntSet(&ret->nextDomID, 1);
420 421 422 423

    return ret;

 error:
424
    virObjectUnref(ret);
425 426 427 428
    return NULL;
}


429 430
static const char *defaultConnXML =
"<node>"
431 432
"<domain type='test'>"
"  <name>test</name>"
433
"  <uuid>6695eb01-f6a4-8304-79aa-97f2502e193f</uuid>"
434 435 436 437 438 439
"  <memory>8388608</memory>"
"  <currentMemory>2097152</currentMemory>"
"  <vcpu>2</vcpu>"
"  <os>"
"    <type>hvm</type>"
"  </os>"
440
"  <devices>"
441 442 443 444 445
"    <disk type='file' device='disk'>"
"      <source file='/guest/diskimage1'/>"
"      <target dev='vda' bus='virtio'/>"
"      <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>"
"    </disk>"
446 447 448 449 450 451
"    <interface type='network'>"
"      <mac address='aa:bb:cc:dd:ee:ff'/>"
"      <source network='default' bridge='virbr0'/>"
"      <address type='pci' domain='0x0000' bus='0x00' slot='0x1' function='0x0'/>"
"    </interface>"
"  </devices>"
452 453
"</domain>"
""
454 455
"<network>"
"  <name>default</name>"
456
"  <uuid>dd8fe884-6c02-601e-7551-cca97df1c5df</uuid>"
457
"  <bridge name='virbr0'/>"
458 459 460
"  <forward/>"
"  <ip address='192.168.122.1' netmask='255.255.255.0'>"
"    <dhcp>"
461
"      <range start='192.168.122.2' end='192.168.122.254'/>"
462 463
"    </dhcp>"
"  </ip>"
464 465
"</network>"
""
L
Laine Stump 已提交
466 467 468 469 470 471 472 473
"<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>"
474 475
"</interface>"
""
C
Cole Robinson 已提交
476 477
"<pool type='dir'>"
"  <name>default-pool</name>"
478
"  <uuid>dfe224cb-28fb-8dd0-c4b2-64eb3f0f4566</uuid>"
C
Cole Robinson 已提交
479 480 481
"  <target>"
"    <path>/default-pool</path>"
"  </target>"
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
"</pool>"
""
"<device>"
"  <name>computer</name>"
"  <capability type='system'>"
"    <hardware>"
"      <vendor>Libvirt</vendor>"
"      <version>Test driver</version>"
"      <serial>123456</serial>"
"      <uuid>11111111-2222-3333-4444-555555555555</uuid>"
"    </hardware>"
"    <firmware>"
"      <vendor>Libvirt</vendor>"
"      <version>Test Driver</version>"
"      <release_date>01/22/2007</release_date>"
"    </firmware>"
"  </capability>"
"</device>"
500
"<device>"
501
"  <name>scsi_host1</name>"
502 503 504
"  <parent>computer</parent>"
"  <capability type='scsi_host'>"
"    <host>1</host>"
505
"    <unique_id>0</unique_id>"
506 507 508
"    <capability type='fc_host'>"
"      <wwnn>2000000012341234</wwnn>"
"      <wwpn>1000000012341234</wwpn>"
509 510 511 512
"      <fabric_wwn>2000000043214321</fabric_wwn>"
"    </capability>"
"    <capability type='vport_ops'>"
"      <max_vports>127</max_vports>"
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529
"      <vports>1</vports>"
"    </capability>"
"  </capability>"
"</device>"
"<device>"
"  <name>scsi_host2</name>"
"  <parent>computer</parent>"
"  <capability type='scsi_host'>"
"    <host>2</host>"
"    <unique_id>1</unique_id>"
"    <capability type='fc_host'>"
"      <wwnn>2000000056785678</wwnn>"
"      <wwpn>1000000056785678</wwpn>"
"      <fabric_wwn>2000000087658765</fabric_wwn>"
"    </capability>"
"    <capability type='vport_ops'>"
"      <max_vports>127</max_vports>"
530
"      <vports>0</vports>"
531 532 533
"    </capability>"
"  </capability>"
"</device>"
534 535 536 537 538 539 540 541 542 543 544 545 546
"<device>"
"  <name>scsi_host11</name>"
"  <parent>scsi_host1</parent>"
"  <capability type='scsi_host'>"
"    <host>11</host>"
"    <unique_id>10</unique_id>"
"    <capability type='fc_host'>"
"      <wwnn>2000000034563456</wwnn>"
"      <wwpn>1000000034563456</wwpn>"
"      <fabric_wwn>2000000043214321</fabric_wwn>"
"    </capability>"
"  </capability>"
 "</device>"
547 548
"</node>";

C
Cole Robinson 已提交
549

550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
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";

573
static const unsigned long long defaultPoolCap = (100 * 1024 * 1024 * 1024ull);
574
static const unsigned long long defaultPoolAlloc;
C
Cole Robinson 已提交
575

576
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr obj);
577
static int testNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
578
static virNetworkObjPtr testNetworkObjFindByName(testDriverPtr privconn, const char *name);
579

580 581 582 583
static virDomainObjPtr
testDomObjFromDomain(virDomainPtr domain)
{
    virDomainObjPtr vm;
584
    testDriverPtr driver = domain->conn->privateData;
585 586
    char uuidstr[VIR_UUID_STRING_BUFLEN];

587
    vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
588 589 590 591 592 593 594 595 596 597
    if (!vm) {
        virUUIDFormat(domain->uuid, uuidstr);
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching uuid '%s' (%s)"),
                       uuidstr, domain->name);
    }

    return vm;
}

598
static char *
599 600
testDomainGenerateIfname(virDomainDefPtr domdef)
{
601
    int maxif = 1024;
602
    int ifctr;
603 604

    for (ifctr = 0; ifctr < maxif; ++ifctr) {
M
Michal Privoznik 已提交
605
        virDomainNetDefPtr net = NULL;
606 607
        char *ifname;

608
        if (virAsprintf(&ifname, "testnet%d", ifctr) < 0)
609 610 611
            return NULL;

        /* Generate network interface names */
M
Michal Privoznik 已提交
612
        if (!(net = virDomainNetFindByName(domdef, ifname)))
613
            return ifname;
614
        VIR_FREE(ifname);
615 616
    }

617 618
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Exceeded max iface limit %d"), maxif);
619 620 621
    return NULL;
}

622
static int
623
testDomainGenerateIfnames(virDomainDefPtr domdef)
624
{
625
    size_t i = 0;
626 627 628 629 630 631

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

632
        ifname = testDomainGenerateIfname(domdef);
633
        if (!ifname)
634
            return -1;
635 636 637 638

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

639
    return 0;
640 641
}

642

643 644
static void
testDomainShutdownState(virDomainPtr domain,
J
Jiri Denemark 已提交
645 646
                        virDomainObjPtr privdom,
                        virDomainShutoffReason reason)
647
{
648
    virDomainObjRemoveTransientDef(privdom);
J
Jiri Denemark 已提交
649
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF, reason);
650

651 652 653 654
    if (domain)
        domain->id = -1;
}

655
/* Set up domain runtime state */
656
static int
657
testDomainStartState(testDriverPtr privconn,
J
Jiri Denemark 已提交
658 659
                     virDomainObjPtr dom,
                     virDomainRunningReason reason)
660
{
661
    int ret = -1;
662

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

666
    if (virDomainObjSetDefTransient(privconn->caps,
667
                                    privconn->xmlopt,
668
                                    dom) < 0) {
669 670 671
        goto cleanup;
    }

C
Cole Robinson 已提交
672
    dom->hasManagedSave = false;
673
    ret = 0;
674
 cleanup:
675
    if (ret < 0)
J
Jiri Denemark 已提交
676
        testDomainShutdownState(NULL, dom, VIR_DOMAIN_SHUTOFF_FAILED);
677
    return ret;
678
}
679

680

681
static char *testBuildFilename(const char *relativeTo,
682 683
                               const char *filename)
{
684 685
    char *offset;
    int baseLen;
686 687
    char *ret;

688
    if (!filename || filename[0] == '\0')
689
        return NULL;
690 691 692 693
    if (filename[0] == '/') {
        ignore_value(VIR_STRDUP(ret, filename));
        return ret;
    }
694

695
    offset = strrchr(relativeTo, '/');
696
    if ((baseLen = (offset-relativeTo+1))) {
697
        char *absFile;
C
Chris Lalancette 已提交
698 699
        int totalLen = baseLen + strlen(filename) + 1;
        if (VIR_ALLOC_N(absFile, totalLen) < 0)
700
            return NULL;
701
        if (virStrncpy(absFile, relativeTo, baseLen, totalLen) < 0) {
C
Chris Lalancette 已提交
702 703 704
            VIR_FREE(absFile);
            return NULL;
        }
705 706 707
        strcat(absFile, filename);
        return absFile;
    } else {
708 709
        ignore_value(VIR_STRDUP(ret, filename));
        return ret;
710
    }
711 712
}

C
Cole Robinson 已提交
713 714 715 716 717 718
static xmlNodePtr
testParseXMLDocFromFile(xmlNodePtr node, const char *file, const char *type)
{
    xmlNodePtr ret = NULL;
    xmlDocPtr doc = NULL;
    char *absFile = NULL;
719
    VIR_AUTOFREE(char *) relFile = NULL;
C
Cole Robinson 已提交
720

721
    if ((relFile = virXMLPropString(node, "file"))) {
C
Cole Robinson 已提交
722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742
        absFile = testBuildFilename(file, 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;
    }

743
 error:
C
Cole Robinson 已提交
744 745 746 747
    xmlFreeDoc(doc);
    return ret;
}

748 749 750 751 752
static int
testParseNodeInfo(virNodeInfoPtr nodeInfo, xmlXPathContextPtr ctxt)
{
    long l;
    int ret;
753
    VIR_AUTOFREE(char *) str = NULL;
754

755
    ret = virXPathLong("string(/node/cpu/nodes[1])", ctxt, &l);
756 757 758
    if (ret == 0) {
        nodeInfo->nodes = l;
    } else if (ret == -2) {
759 760
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu nodes value"));
761
        goto error;
762
    }
763

764
    ret = virXPathLong("string(/node/cpu/sockets[1])", ctxt, &l);
765 766 767
    if (ret == 0) {
        nodeInfo->sockets = l;
    } else if (ret == -2) {
768 769
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu sockets value"));
770
        goto error;
771
    }
772

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

782
    ret = virXPathLong("string(/node/cpu/threads[1])", ctxt, &l);
783 784 785
    if (ret == 0) {
        nodeInfo->threads = l;
    } else if (ret == -2) {
786 787
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu threads value"));
788
        goto error;
789
    }
790

791 792
    nodeInfo->cpus = (nodeInfo->cores * nodeInfo->threads *
                      nodeInfo->sockets * nodeInfo->nodes);
793
    ret = virXPathLong("string(/node/cpu/active[1])", ctxt, &l);
794
    if (ret == 0) {
795
        if (l < nodeInfo->cpus)
796
            nodeInfo->cpus = l;
797
    } else if (ret == -2) {
798 799
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu active value"));
800
        goto error;
801
    }
802
    ret = virXPathLong("string(/node/cpu/mhz[1])", ctxt, &l);
803 804 805
    if (ret == 0) {
        nodeInfo->mhz = l;
    } else if (ret == -2) {
806 807
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu mhz value"));
808
        goto error;
809 810
    }

811
    str = virXPathString("string(/node/cpu/model[1])", ctxt);
812
    if (str != NULL) {
813
        if (virStrcpyStatic(nodeInfo->model, str) < 0) {
814 815
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Model %s too big for destination"), str);
C
Chris Lalancette 已提交
816 817
            goto error;
        }
818 819
    }

820
    ret = virXPathLong("string(/node/memory[1])", ctxt, &l);
821 822 823
    if (ret == 0) {
        nodeInfo->memory = l;
    } else if (ret == -2) {
824 825
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node memory value"));
826
        goto error;
827
    }
828

829
    return 0;
830
 error:
831 832 833
    return -1;
}

834
static int
835
testParseDomainSnapshots(testDriverPtr privconn,
836 837 838 839 840 841 842 843
                         virDomainObjPtr domobj,
                         const char *file,
                         xmlXPathContextPtr ctxt)
{
    size_t i;
    int ret = -1;
    testDomainNamespaceDefPtr nsdata = domobj->def->namespaceData;
    xmlNodePtr *nodes = nsdata->snap_nodes;
844
    bool cur;
845 846

    for (i = 0; i < nsdata->num_snap_nodes; i++) {
847
        virDomainMomentObjPtr snap;
848 849 850 851 852 853 854 855 856
        virDomainSnapshotDefPtr def;
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                  "domainsnapshot");
        if (!node)
            goto error;

        def = virDomainSnapshotDefParseNode(ctxt->doc, node,
                                            privconn->caps,
                                            privconn->xmlopt,
857
                                            &cur,
858 859 860 861 862 863 864
                                            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))) {
865
            virObjectUnref(def);
866 867 868
            goto error;
        }

869
        if (cur) {
870
            if (virDomainSnapshotGetCurrent(domobj->snapshots)) {
871 872 873 874 875
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("more than one snapshot claims to be active"));
                goto error;
            }

876
            virDomainSnapshotSetCurrent(domobj->snapshots, snap);
877 878 879 880 881 882 883 884 885 886 887
        }
    }

    if (virDomainSnapshotUpdateRelations(domobj->snapshots) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Snapshots have inconsistent relations for "
                         "domain %s"), domobj->def->name);
        goto error;
    }

    ret = 0;
888
 error:
889 890 891
    return ret;
}

892
static int
893
testParseDomains(testDriverPtr privconn,
C
Cole Robinson 已提交
894 895
                 const char *file,
                 xmlXPathContextPtr ctxt)
896 897 898
{
    int num, ret = -1;
    size_t i;
899
    virDomainObjPtr obj = NULL;
900
    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
901 902

    num = virXPathNodeSet("/node/domain", ctxt, &nodes);
903
    if (num < 0)
904
        return -1;
905

906
    for (i = 0; i < num; i++) {
907
        virDomainDefPtr def;
908
        testDomainNamespaceDefPtr nsdata;
C
Cole Robinson 已提交
909 910 911 912 913
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file, "domain");
        if (!node)
            goto error;

        def = virDomainDefParseNode(ctxt->doc, node,
914
                                    privconn->caps, privconn->xmlopt, NULL,
915
                                    VIR_DOMAIN_DEF_PARSE_INACTIVE);
C
Cole Robinson 已提交
916 917
        if (!def)
            goto error;
918

919
        if (testDomainGenerateIfnames(def) < 0 ||
920
            !(obj = virDomainObjListAdd(privconn->domains,
921
                                        def,
922
                                        privconn->xmlopt,
923
                                        0, NULL))) {
924
            virDomainDefFree(def);
925 926
            goto error;
        }
927

928
        if (testParseDomainSnapshots(privconn, obj, file, ctxt) < 0)
929 930
            goto error;

931
        nsdata = def->namespaceData;
932
        obj->persistent = !nsdata->transient;
C
Cole Robinson 已提交
933
        obj->hasManagedSave = nsdata->hasManagedSave;
934 935 936

        if (nsdata->runstate != VIR_DOMAIN_SHUTOFF) {
            if (testDomainStartState(privconn, obj,
937
                                     VIR_DOMAIN_RUNNING_BOOTED) < 0)
938 939 940
                goto error;
        } else {
            testDomainShutdownState(NULL, obj, 0);
941
        }
942
        virDomainObjSetState(obj, nsdata->runstate, 0);
943

944
        virDomainObjEndAPI(&obj);
945
    }
946

947
    ret = 0;
948
 error:
949
    virDomainObjEndAPI(&obj);
950 951 952
    return ret;
}

953

954
static int
955
testParseNetworks(testDriverPtr privconn,
C
Cole Robinson 已提交
956 957
                  const char *file,
                  xmlXPathContextPtr ctxt)
958
{
959
    int num;
960 961
    size_t i;
    virNetworkObjPtr obj;
962
    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
963 964

    num = virXPathNodeSet("/node/network", ctxt, &nodes);
965
    if (num < 0)
966
        return -1;
967 968

    for (i = 0; i < num; i++) {
969
        virNetworkDefPtr def;
C
Cole Robinson 已提交
970 971
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file, "network");
        if (!node)
972
            return -1;
973

C
Cole Robinson 已提交
974 975
        def = virNetworkDefParseNode(ctxt->doc, node);
        if (!def)
976
            return -1;
977

978
        if (!(obj = virNetworkObjAssignDef(privconn->networks, def, 0))) {
979
            virNetworkDefFree(def);
980
            return -1;
981
        }
982

983
        virNetworkObjSetActive(obj, true);
984
        virNetworkObjEndAPI(&obj);
985
    }
986

987
    return 0;
988 989
}

990

991
static int
992
testParseInterfaces(testDriverPtr privconn,
C
Cole Robinson 已提交
993 994
                    const char *file,
                    xmlXPathContextPtr ctxt)
995
{
996
    int num;
997 998
    size_t i;
    virInterfaceObjPtr obj;
999
    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
1000 1001

    num = virXPathNodeSet("/node/interface", ctxt, &nodes);
1002
    if (num < 0)
1003
        return -1;
1004 1005

    for (i = 0; i < num; i++) {
L
Laine Stump 已提交
1006
        virInterfaceDefPtr def;
C
Cole Robinson 已提交
1007 1008 1009
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "interface");
        if (!node)
1010
            return -1;
L
Laine Stump 已提交
1011

C
Cole Robinson 已提交
1012 1013
        def = virInterfaceDefParseNode(ctxt->doc, node);
        if (!def)
1014
            return -1;
1015

1016
        if (!(obj = virInterfaceObjListAssignDef(privconn->ifaces, def))) {
L
Laine Stump 已提交
1017
            virInterfaceDefFree(def);
1018
            return -1;
L
Laine Stump 已提交
1019
        }
1020

1021
        virInterfaceObjSetActive(obj, true);
1022
        virInterfaceObjEndAPI(&obj);
1023 1024
    }

1025
    return 0;
1026 1027
}

1028

1029
static int
C
Cole Robinson 已提交
1030
testOpenVolumesForPool(const char *file,
1031
                       xmlXPathContextPtr ctxt,
1032 1033
                       virStoragePoolObjPtr obj,
                       int objidx)
1034
{
1035
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(obj);
1036
    size_t i;
1037 1038 1039
    int num;
    VIR_AUTOFREE(char *) vol_xpath = NULL;
    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
1040
    VIR_AUTOPTR(virStorageVolDef) volDef = NULL;
1041 1042

    /* Find storage volumes */
1043
    if (virAsprintf(&vol_xpath, "/node/pool[%d]/volume", objidx) < 0)
1044
        return -1;
1045 1046

    num = virXPathNodeSet(vol_xpath, ctxt, &nodes);
1047
    if (num < 0)
1048
        return -1;
1049 1050

    for (i = 0; i < num; i++) {
C
Cole Robinson 已提交
1051 1052 1053
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "volume");
        if (!node)
1054
            return -1;
1055

1056
        if (!(volDef = virStorageVolDefParseNode(def, ctxt->doc, node, 0)))
1057
            return -1;
1058

1059 1060
        if (!volDef->target.path) {
            if (virAsprintf(&volDef->target.path, "%s/%s",
1061
                            def->target.path, volDef->name) < 0)
1062
                return -1;
1063 1064
        }

1065
        if (!volDef->key && VIR_STRDUP(volDef->key, volDef->target.path) < 0)
1066
            return -1;
1067

1068
        if (virStoragePoolObjAddVol(obj, volDef) < 0)
1069
            return -1;
1070

1071 1072
        def->allocation += volDef->target.allocation;
        def->available = (def->capacity - def->allocation);
1073
        volDef = NULL;
L
Laine Stump 已提交
1074 1075
    }

1076
    return 0;
1077 1078
}

1079

1080
static int
1081
testParseStorage(testDriverPtr privconn,
C
Cole Robinson 已提交
1082 1083
                 const char *file,
                 xmlXPathContextPtr ctxt)
1084
{
1085
    int num;
1086 1087
    size_t i;
    virStoragePoolObjPtr obj;
1088
    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
1089 1090

    num = virXPathNodeSet("/node/pool", ctxt, &nodes);
1091
    if (num < 0)
1092
        return -1;
1093 1094

    for (i = 0; i < num; i++) {
C
Cole Robinson 已提交
1095
        virStoragePoolDefPtr def;
C
Cole Robinson 已提交
1096 1097 1098
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "pool");
        if (!node)
1099
            return -1;
C
Cole Robinson 已提交
1100

C
Cole Robinson 已提交
1101 1102
        def = virStoragePoolDefParseNode(ctxt->doc, node);
        if (!def)
1103
            return -1;
C
Cole Robinson 已提交
1104

1105
        if (!(obj = virStoragePoolObjAssignDef(privconn->pools, def, false))) {
C
Cole Robinson 已提交
1106
            virStoragePoolDefFree(def);
1107
            return -1;
C
Cole Robinson 已提交
1108 1109
        }

1110
        if (testStoragePoolObjSetDefaults(obj) == -1) {
1111
            virStoragePoolObjEndAPI(&obj);
1112
            return -1;
1113
        }
1114
        virStoragePoolObjSetActive(obj, true);
1115 1116

        /* Find storage volumes */
C
Cole Robinson 已提交
1117
        if (testOpenVolumesForPool(file, ctxt, obj, i+1) < 0) {
1118
            virStoragePoolObjEndAPI(&obj);
1119
            return -1;
1120 1121
        }

1122
        virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
1123 1124
    }

1125
    return 0;
1126 1127
}

1128

1129
static int
1130
testParseNodedevs(testDriverPtr privconn,
C
Cole Robinson 已提交
1131 1132
                  const char *file,
                  xmlXPathContextPtr ctxt)
1133
{
1134
    int num;
1135 1136
    size_t i;
    virNodeDeviceObjPtr obj;
1137
    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
1138 1139

    num = virXPathNodeSet("/node/device", ctxt, &nodes);
1140
    if (num < 0)
1141
        return -1;
1142 1143

    for (i = 0; i < num; i++) {
1144
        virNodeDeviceDefPtr def;
C
Cole Robinson 已提交
1145 1146 1147
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                  "nodedev");
        if (!node)
1148
            return -1;
1149

C
Cole Robinson 已提交
1150 1151
        def = virNodeDeviceDefParseNode(ctxt->doc, node, 0, NULL);
        if (!def)
1152
            return -1;
1153

1154
        if (!(obj = virNodeDeviceObjListAssignDef(privconn->devs, def))) {
1155
            virNodeDeviceDefFree(def);
1156
            return -1;
1157
        }
1158

1159
        virNodeDeviceObjSetSkipUpdateCaps(obj, true);
1160
        virNodeDeviceObjEndAPI(&obj);
1161 1162
    }

1163
    return 0;
1164 1165
}

1166
static int
1167
testParseAuthUsers(testDriverPtr privconn,
1168 1169
                   xmlXPathContextPtr ctxt)
{
1170
    int num;
1171
    size_t i;
1172
    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
1173 1174 1175

    num = virXPathNodeSet("/node/auth/user", ctxt, &nodes);
    if (num < 0)
1176
        return -1;
1177 1178 1179

    privconn->numAuths = num;
    if (num && VIR_ALLOC_N(privconn->auths, num) < 0)
1180
        return -1;
1181 1182

    for (i = 0; i < num; i++) {
1183
        VIR_AUTOFREE(char *) username = NULL;
1184 1185 1186 1187 1188 1189

        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"));
1190
            return -1;
1191 1192
        }
        /* This field is optional. */
1193 1194
        privconn->auths[i].password = virXMLPropString(nodes[i], "password");
        VIR_STEAL_PTR(privconn->auths[i].username, username);
1195 1196
    }

1197
    return 0;
1198
}
1199

C
Cole Robinson 已提交
1200 1201 1202 1203 1204
static int
testOpenParse(testDriverPtr privconn,
              const char *file,
              xmlXPathContextPtr ctxt)
{
1205
    if (!virXMLNodeNameEqual(ctxt->node, "node")) {
C
Cole Robinson 已提交
1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("Root element is not 'node'"));
        goto error;
    }

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

    return 0;
 error:
    return -1;
}

1231 1232
/* No shared state between simultaneous test connections initialized
 * from a file.  */
1233 1234 1235 1236 1237
static int
testOpenFromFile(virConnectPtr conn, const char *file)
{
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
1238
    testDriverPtr privconn;
1239

1240
    if (!(privconn = testDriverNew()))
1241
        return VIR_DRV_OPEN_ERROR;
1242

1243
    virObjectLock(privconn);
1244 1245 1246 1247 1248
    conn->privateData = privconn;

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

1249
    if (!(doc = virXMLParseFileCtxt(file, &ctxt)))
1250 1251 1252 1253 1254
        goto error;

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

C
Cole Robinson 已提交
1255
    if (testOpenParse(privconn, file, ctxt) < 0)
1256
        goto error;
1257

J
Jim Meyering 已提交
1258
    xmlXPathFreeContext(ctxt);
1259
    xmlFreeDoc(doc);
1260
    virObjectUnlock(privconn);
1261

1262
    return VIR_DRV_OPEN_SUCCESS;
1263 1264

 error:
J
Jim Meyering 已提交
1265
    xmlXPathFreeContext(ctxt);
1266
    xmlFreeDoc(doc);
1267
    virObjectUnref(privconn);
1268
    conn->privateData = NULL;
1269
    return VIR_DRV_OPEN_ERROR;
1270 1271
}

1272 1273 1274 1275 1276 1277
/* 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)
{
1278
    int ret = VIR_DRV_OPEN_ERROR;
1279
    testDriverPtr privconn = NULL;
1280 1281
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
1282
    size_t i;
1283 1284

    virMutexLock(&defaultLock);
1285 1286
    if (defaultPrivconn) {
        conn->privateData = virObjectRef(defaultPrivconn);
1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299
        virMutexUnlock(&defaultLock);
        return VIR_DRV_OPEN_SUCCESS;
    }

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

    conn->privateData = privconn;

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

    /* Numa setup */
    privconn->numCells = 2;
1300 1301 1302 1303
    for (i = 0; i < privconn->numCells; i++) {
        privconn->cells[i].numCpus = 8;
        privconn->cells[i].mem = (i + 1) * 2048 * 1024;
        privconn->cells[i].freeMem = (i + 1) * 1024 * 1024;
1304
    }
1305
    for (i = 0; i < 16; i++) {
1306 1307 1308
        virBitmapPtr siblings = virBitmapNew(16);
        if (!siblings)
            goto error;
1309 1310 1311 1312 1313
        ignore_value(virBitmapSetBit(siblings, i));
        privconn->cells[i / 8].cpus[(i % 8)].id = i;
        privconn->cells[i / 8].cpus[(i % 8)].socket_id = i / 8;
        privconn->cells[i / 8].cpus[(i % 8)].core_id = i % 8;
        privconn->cells[i / 8].cpus[(i % 8)].siblings = siblings;
1314 1315 1316 1317 1318
    }

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

1319 1320
    if (!(doc = virXMLParseStringCtxt(defaultConnXML,
                                      _("(test driver)"), &ctxt)))
1321 1322
        goto error;

1323
    if (testOpenParse(privconn, NULL, ctxt) < 0)
1324 1325
        goto error;

1326
    defaultPrivconn = privconn;
1327 1328 1329
    ret = VIR_DRV_OPEN_SUCCESS;
 cleanup:
    virMutexUnlock(&defaultLock);
1330 1331
    xmlXPathFreeContext(ctxt);
    xmlFreeDoc(doc);
1332
    return ret;
1333 1334

 error:
1335
    virObjectUnref(privconn);
1336
    conn->privateData = NULL;
1337
    goto cleanup;
1338 1339
}

1340 1341 1342 1343
static int
testConnectAuthenticate(virConnectPtr conn,
                        virConnectAuthPtr auth)
{
1344
    testDriverPtr privconn = conn->privateData;
1345 1346
    int ret = -1;
    ssize_t i;
1347 1348
    VIR_AUTOFREE(char *) username = NULL;
    VIR_AUTOFREE(char *) password = NULL;
1349

1350
    virObjectLock(privconn);
1351
    if (privconn->numAuths == 0) {
1352
        virObjectUnlock(privconn);
1353
        return 0;
1354
    }
1355 1356 1357 1358

    /* Authentication is required because the test XML contains a
     * non-empty <auth/> section.  First we must ask for a username.
     */
1359 1360
    if (!(username = virAuthGetUsername(conn, auth, "test", NULL,
                                        "localhost"/*?*/)))
1361 1362 1363 1364 1365 1366 1367 1368 1369
        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;

1370
 found_user:
1371 1372
    /* Even if we didn't find the user, we still ask for a password. */
    if (i == -1 || privconn->auths[i].password != NULL) {
1373 1374
        if (!(password = virAuthGetPassword(conn, auth, "test", username,
                                            "localhost")))
1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385
            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;
1386
 cleanup:
1387
    virObjectUnlock(privconn);
1388 1389
    return ret;
}
1390

1391 1392 1393 1394

static void
testDriverCloseInternal(testDriverPtr driver)
{
1395 1396 1397
    virMutexLock(&defaultLock);
    bool disposed = !virObjectUnref(driver);
    if (disposed && driver == defaultPrivconn)
1398
        defaultPrivconn = NULL;
1399
    virMutexUnlock(&defaultLock);
1400 1401 1402 1403 1404 1405 1406 1407
}


static virDrvOpenStatus
testConnectOpen(virConnectPtr conn,
                virConnectAuthPtr auth,
                virConfPtr conf ATTRIBUTE_UNUSED,
                unsigned int flags)
1408
{
1409
    int ret;
1410

E
Eric Blake 已提交
1411 1412
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

1413 1414
    if (conn->uri->path[0] == '\0' ||
        (conn->uri->path[0] == '/' && conn->uri->path[1] == '\0')) {
1415 1416
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("testOpen: supply a path or use test:///default"));
1417 1418
        return VIR_DRV_OPEN_ERROR;
    }
1419

1420
    if (STREQ(conn->uri->path, "/default"))
1421 1422
        ret = testOpenDefault(conn);
    else
1423
        ret = testOpenFromFile(conn,
1424
                               conn->uri->path);
1425

1426 1427 1428
    if (ret != VIR_DRV_OPEN_SUCCESS)
        return ret;

1429
    /* Fake authentication. */
1430 1431 1432
    if (testConnectAuthenticate(conn, auth) < 0) {
        testDriverCloseInternal(conn->privateData);
        conn->privateData = NULL;
1433
        return VIR_DRV_OPEN_ERROR;
1434
    }
1435

1436
    return VIR_DRV_OPEN_SUCCESS;
1437 1438
}

1439

1440 1441 1442 1443
static int
testConnectClose(virConnectPtr conn)
{
    testDriverCloseInternal(conn->privateData);
1444
    conn->privateData = NULL;
1445
    return 0;
1446 1447
}

1448

1449 1450
static int testConnectGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
                                 unsigned long *hvVer)
1451
{
1452
    *hvVer = 2;
1453
    return 0;
1454 1455
}

1456 1457 1458 1459 1460 1461
static char *testConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return virGetHostname();
}


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

1467
static int testConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
1468 1469 1470 1471
{
    return 0;
}

1472
static int testConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
1473 1474 1475 1476
{
    return 1;
}

1477 1478
static int testConnectGetMaxVcpus(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type ATTRIBUTE_UNUSED)
1479 1480 1481 1482
{
    return 32;
}

1483 1484 1485 1486 1487 1488
static char *
testConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED,
                       const char **xmlCPUs,
                       unsigned int ncpus,
                       unsigned int flags)
{
J
Jiri Denemark 已提交
1489 1490 1491
    virCPUDefPtr *cpus = NULL;
    virCPUDefPtr cpu = NULL;
    char *cpustr = NULL;
1492 1493 1494

    virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, NULL);

J
Jiri Denemark 已提交
1495 1496 1497
    if (!(cpus = virCPUDefListParse(xmlCPUs, ncpus, VIR_CPU_TYPE_HOST)))
        goto cleanup;

1498
    if (!(cpu = virCPUBaseline(VIR_ARCH_NONE, cpus, ncpus, NULL, NULL, false)))
J
Jiri Denemark 已提交
1499 1500 1501 1502 1503 1504
        goto cleanup;

    if ((flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) &&
        virCPUExpandFeatures(cpus[0]->arch, cpu) < 0)
        goto cleanup;

1505
    cpustr = virCPUDefFormat(cpu, NULL);
J
Jiri Denemark 已提交
1506 1507 1508 1509

 cleanup:
    virCPUDefListFree(cpus);
    virCPUDefFree(cpu);
1510

J
Jiri Denemark 已提交
1511
    return cpustr;
1512 1513
}

1514 1515
static int testNodeGetInfo(virConnectPtr conn,
                           virNodeInfoPtr info)
1516
{
1517
    testDriverPtr privconn = conn->privateData;
1518
    virObjectLock(privconn);
1519
    memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo));
1520
    virObjectUnlock(privconn);
1521
    return 0;
1522 1523
}

1524
static char *testConnectGetCapabilities(virConnectPtr conn)
1525
{
1526
    testDriverPtr privconn = conn->privateData;
1527
    char *xml;
1528
    virObjectLock(privconn);
1529
    xml = virCapabilitiesFormatXML(privconn->caps);
1530
    virObjectUnlock(privconn);
1531
    return xml;
1532 1533
}

1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553
static char *
testConnectGetSysinfo(virConnectPtr conn ATTRIBUTE_UNUSED,
                      unsigned int flags)
{
    char *ret;
    const char *sysinfo = "<sysinfo type='smbios'>\n"
           "  <bios>\n"
           "    <entry name='vendor'>LENOVO</entry>\n"
           "    <entry name='version'>G4ETA1WW (2.61 )</entry>\n"
           "    <entry name='date'>05/07/2014</entry>\n"
           "    <entry name='release'>2.61</entry>\n"
           "  </bios>\n"
           "</sysinfo>\n";

    virCheckFlags(0, NULL);

    ignore_value(VIR_STRDUP(ret, sysinfo));
    return ret;
}

1554 1555 1556 1557 1558 1559
static const char *
testConnectGetType(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return "TEST";
}

1560
static int testConnectNumOfDomains(virConnectPtr conn)
1561
{
1562
    testDriverPtr privconn = conn->privateData;
1563
    int count;
1564

1565
    virObjectLock(privconn);
1566
    count = virDomainObjListNumOfDomains(privconn->domains, true, NULL, NULL);
1567
    virObjectUnlock(privconn);
1568

1569
    return count;
1570 1571
}

1572 1573 1574
static int testDomainIsActive(virDomainPtr dom)
{
    virDomainObjPtr obj;
1575
    int ret;
1576

1577 1578
    if (!(obj = testDomObjFromDomain(dom)))
        return -1;
1579

1580 1581
    ret = virDomainObjIsActive(obj);
    virDomainObjEndAPI(&obj);
1582 1583 1584 1585 1586 1587
    return ret;
}

static int testDomainIsPersistent(virDomainPtr dom)
{
    virDomainObjPtr obj;
1588 1589 1590 1591
    int ret;

    if (!(obj = testDomObjFromDomain(dom)))
        return -1;
1592 1593 1594

    ret = obj->persistent;

1595
    virDomainObjEndAPI(&obj);
1596 1597 1598
    return ret;
}

1599 1600 1601 1602 1603
static int testDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
{
    return 0;
}

1604
static virDomainPtr
1605
testDomainCreateXML(virConnectPtr conn, const char *xml,
1606
                      unsigned int flags)
1607
{
1608
    testDriverPtr privconn = conn->privateData;
1609
    virDomainPtr ret = NULL;
1610
    virDomainDefPtr def;
1611
    virDomainObjPtr dom = NULL;
1612
    virObjectEventPtr event = NULL;
1613
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
1614

1615 1616 1617
    virCheckFlags(VIR_DOMAIN_START_VALIDATE, NULL);

    if (flags & VIR_DOMAIN_START_VALIDATE)
1618
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
1619

1620
    virObjectLock(privconn);
1621
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
1622
                                       NULL, parse_flags)) == NULL)
1623
        goto cleanup;
1624

1625
    if (testDomainGenerateIfnames(def) < 0)
1626
        goto cleanup;
1627
    if (!(dom = virDomainObjListAdd(privconn->domains,
1628
                                    def,
1629
                                    privconn->xmlopt,
1630
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
1631 1632
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
1633 1634
        goto cleanup;
    def = NULL;
1635

1636
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_BOOTED) < 0) {
1637
        if (!dom->persistent)
1638
            virDomainObjListRemove(privconn->domains, dom);
1639
        goto cleanup;
1640
    }
1641

1642
    event = virDomainEventLifecycleNewFromObj(dom,
1643 1644 1645
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);

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

1648
 cleanup:
1649
    virDomainObjEndAPI(&dom);
1650
    virObjectEventStateQueue(privconn->eventState, event);
1651
    virDomainDefFree(def);
1652
    virObjectUnlock(privconn);
1653
    return ret;
1654 1655 1656
}


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

1664
    if (!(dom = virDomainObjListFindByID(privconn->domains, id))) {
1665
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1666
        return NULL;
1667 1668
    }

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

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

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

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

1687
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
1688

1689
    virDomainObjEndAPI(&dom);
1690
    return ret;
1691 1692
}

1693
static virDomainPtr testDomainLookupByName(virConnectPtr conn,
1694
                                           const char *name)
1695
{
1696
    testDriverPtr privconn = conn->privateData;
1697 1698
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1699

1700
    if (!(dom = virDomainObjListFindByName(privconn->domains, name))) {
1701
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1702
        goto cleanup;
1703
    }
1704

1705
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
1706

1707
 cleanup:
1708
    virDomainObjEndAPI(&dom);
1709
    return ret;
1710 1711
}

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

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

1722 1723
static int testDomainDestroyFlags(virDomainPtr domain,
                                  unsigned int flags)
1724
{
1725
    testDriverPtr privconn = domain->conn->privateData;
1726
    virDomainObjPtr privdom;
1727
    virObjectEventPtr event = NULL;
1728
    int ret = -1;
1729

1730 1731
    virCheckFlags(VIR_DOMAIN_DESTROY_GRACEFUL, -1);

1732
    if (!(privdom = testDomObjFromDomain(domain)))
1733
        goto cleanup;
1734

1735
    if (virDomainObjCheckActive(privdom) < 0)
1736 1737
        goto cleanup;

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

1743
    if (!privdom->persistent)
1744
        virDomainObjListRemove(privconn->domains, privdom);
1745 1746

    ret = 0;
1747
 cleanup:
1748
    virDomainObjEndAPI(&privdom);
1749
    virObjectEventStateQueue(privconn->eventState, event);
1750
    return ret;
1751 1752
}

1753 1754 1755 1756 1757
static int testDomainDestroy(virDomainPtr domain)
{
    return testDomainDestroyFlags(domain, 0);
}

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

1765 1766
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1767

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

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

1781
 cleanup:
1782
    virDomainObjEndAPI(&privdom);
1783
    virObjectEventStateQueue(privconn->eventState, event);
1784
    return ret;
1785 1786
}

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

1795 1796
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1797

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

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

1811
 cleanup:
1812
    virDomainObjEndAPI(&privdom);
1813
    virObjectEventStateQueue(privconn->eventState, event);
1814
    return ret;
1815 1816
}

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

1825 1826
    virCheckFlags(0, -1);

1827

1828
    if (!(privdom = testDomObjFromDomain(domain)))
1829
        goto cleanup;
1830

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

J
Jiri Denemark 已提交
1837
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1838
    event = virDomainEventLifecycleNewFromObj(privdom,
1839 1840
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1841

1842
    if (!privdom->persistent)
1843
        virDomainObjListRemove(privconn->domains, privdom);
1844

1845
    ret = 0;
1846
 cleanup:
1847
    virDomainObjEndAPI(&privdom);
1848
    virObjectEventStateQueue(privconn->eventState, event);
1849
    return ret;
1850 1851
}

1852
static int testDomainShutdown(virDomainPtr domain)
1853
{
1854
    return testDomainShutdownFlags(domain, 0);
1855 1856
}

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

1866 1867 1868 1869 1870 1871
    virCheckFlags(VIR_DOMAIN_REBOOT_DEFAULT |
                  VIR_DOMAIN_REBOOT_ACPI_POWER_BTN |
                  VIR_DOMAIN_REBOOT_GUEST_AGENT |
                  VIR_DOMAIN_REBOOT_INITCTL |
                  VIR_DOMAIN_REBOOT_SIGNAL |
                  VIR_DOMAIN_REBOOT_PARAVIRT, -1);
1872

1873
    if (!(privdom = testDomObjFromDomain(domain)))
1874
        goto cleanup;
1875

1876
    if (virDomainObjCheckActive(privdom) < 0)
1877 1878
        goto cleanup;

J
Jiri Denemark 已提交
1879 1880 1881
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTDOWN,
                         VIR_DOMAIN_SHUTDOWN_USER);

1882
    switch (privdom->def->onReboot) {
1883
    case VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY:
J
Jiri Denemark 已提交
1884 1885
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1886 1887
        break;

1888
    case VIR_DOMAIN_LIFECYCLE_ACTION_RESTART:
J
Jiri Denemark 已提交
1889 1890
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
1891 1892
        break;

1893
    case VIR_DOMAIN_LIFECYCLE_ACTION_PRESERVE:
J
Jiri Denemark 已提交
1894 1895
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1896 1897
        break;

1898
    case VIR_DOMAIN_LIFECYCLE_ACTION_RESTART_RENAME:
J
Jiri Denemark 已提交
1899 1900
        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
1901
        break;
1902

1903
    default:
J
Jiri Denemark 已提交
1904 1905
        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1906 1907
        break;
    }
1908

J
Jiri Denemark 已提交
1909 1910
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1911
        event = virDomainEventLifecycleNewFromObj(privdom,
1912 1913
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1914

1915
        if (!privdom->persistent)
1916
            virDomainObjListRemove(privconn->domains, privdom);
1917 1918
    }

1919
    ret = 0;
1920
 cleanup:
1921
    virDomainObjEndAPI(&privdom);
1922
    virObjectEventStateQueue(privconn->eventState, event);
1923
    return ret;
1924 1925
}

1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949

static char *
testDomainGetHostname(virDomainPtr domain,
                      unsigned int flags)
{
    char *ret = NULL;
    virDomainObjPtr vm = NULL;

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
        goto cleanup;

    if (virDomainObjCheckActive(vm) < 0)
        goto cleanup;

    ignore_value(virAsprintf(&ret, "%shost", domain->name));

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


1950
static int testDomainGetInfo(virDomainPtr domain,
1951
                             virDomainInfoPtr info)
1952
{
1953
    struct timeval tv;
1954
    virDomainObjPtr privdom;
1955
    int ret = -1;
1956

1957 1958
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1959 1960

    if (gettimeofday(&tv, NULL) < 0) {
1961 1962
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("getting time of day"));
1963
        goto cleanup;
1964 1965
    }

J
Jiri Denemark 已提交
1966
    info->state = virDomainObjGetState(privdom, NULL);
1967
    info->memory = privdom->def->mem.cur_balloon;
1968
    info->maxMem = virDomainDefGetMemoryTotal(privdom->def);
1969
    info->nrVirtCpu = virDomainDefGetVcpus(privdom->def);
1970
    info->cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
1971 1972
    ret = 0;

1973
 cleanup:
1974
    virDomainObjEndAPI(&privdom);
1975
    return ret;
1976 1977
}

1978 1979 1980 1981 1982 1983 1984 1985 1986 1987
static int
testDomainGetState(virDomainPtr domain,
                   int *state,
                   int *reason,
                   unsigned int flags)
{
    virDomainObjPtr privdom;

    virCheckFlags(0, -1);

1988 1989
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1990

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

1993
    virDomainObjEndAPI(&privdom);
1994 1995

    return 0;
1996 1997
}

1998
static int
1999
testDomainGetTime(virDomainPtr dom,
2000 2001 2002 2003
                  long long *seconds,
                  unsigned int *nseconds,
                  unsigned int flags)
{
2004 2005 2006
    virDomainObjPtr vm = NULL;
    int ret = -1;

2007 2008
    virCheckFlags(0, -1);

2009 2010 2011 2012 2013 2014 2015 2016 2017
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;

    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("domain is not running"));
        goto cleanup;
    }

2018 2019 2020
    *seconds = 627319920;
    *nseconds = 0;

2021 2022 2023 2024
    ret = 0;
 cleanup:
    virDomainObjEndAPI(&vm);
    return ret;
2025 2026
}

2027 2028
#define TEST_SAVE_MAGIC "TestGuestMagic"

2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041

/**
 * testDomainSaveImageWrite:
 * @driver: test driver data
 * @def: domain definition whose XML will be stored in the image
 * @path: path to the saved image
 *
 * Returns true on success, else false.
 */
static bool
testDomainSaveImageWrite(testDriverPtr driver,
                         const char *path,
                         virDomainDefPtr def)
2042
{
2043
    int len;
2044
    int fd = -1;
2045
    VIR_AUTOFREE(char *) xml = NULL;
2046

2047
    xml = virDomainDefFormat(def, driver->caps, VIR_DOMAIN_DEF_FORMAT_SECURE);
C
Cole Robinson 已提交
2048

2049
    if (xml == NULL) {
2050
        virReportSystemError(errno,
2051
                             _("saving domain '%s' failed to allocate space for metadata"),
2052 2053
                             def->name);
        goto error;
2054
    }
2055 2056

    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
2057
        virReportSystemError(errno,
2058
                             _("saving domain '%s' to '%s': open failed"),
2059 2060
                             def->name, path);
        goto error;
2061
    }
2062

2063
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
2064
        virReportSystemError(errno,
2065
                             _("saving domain '%s' to '%s': write failed"),
2066 2067
                             def->name, path);
        goto error;
2068
    }
2069 2070

    len = strlen(xml);
2071
    if (safewrite(fd, (char*)&len, sizeof(len)) < 0) {
2072
        virReportSystemError(errno,
2073
                             _("saving domain '%s' to '%s': write failed"),
2074 2075
                             def->name, path);
        goto error;
2076
    }
2077

2078
    if (safewrite(fd, xml, len) < 0) {
2079
        virReportSystemError(errno,
2080
                             _("saving domain '%s' to '%s': write failed"),
2081 2082
                             def->name, path);
        goto error;
2083
    }
2084

2085
    if (VIR_CLOSE(fd) < 0) {
2086
        virReportSystemError(errno,
2087
                             _("saving domain '%s' to '%s': write failed"),
2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104
                             def->name, path);
        goto error;
    }

    return true;

 error:
    /* Don't report failure in close or unlink, because
     * in either case we're already in a failure scenario
     * and have reported an earlier error */
    VIR_FORCE_CLOSE(fd);
    unlink(path);

    return false;
}


2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176
/**
 * testDomainSaveImageOpen:
 * @driver: test driver data
 * @path: path of the saved image
 * @ret_def: returns domain definition created from the XML stored in the image
 *
 * Returns the opened fd of the save image file and fills ret_def on success.
 * Returns -1, on error.
 */
static int ATTRIBUTE_NONNULL(3)
testDomainSaveImageOpen(testDriverPtr driver,
                        const char *path,
                        virDomainDefPtr *ret_def)
{
    char magic[15];
    int fd = -1;
    int len;
    virDomainDefPtr def = NULL;
    VIR_AUTOFREE(char *) xml = NULL;

    if ((fd = open(path, O_RDONLY)) < 0) {
        virReportSystemError(errno, _("cannot read domain image '%s'"), path);
        goto error;
    }

    if (saferead(fd, magic, sizeof(magic)) != sizeof(magic)) {
        virReportSystemError(errno, _("incomplete save header in '%s'"), path);
        goto error;
    }

    if (memcmp(magic, TEST_SAVE_MAGIC, sizeof(magic))) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("mismatched header magic"));
        goto error;
    }

    if (saferead(fd, (char*)&len, sizeof(len)) != sizeof(len)) {
        virReportSystemError(errno,
                             _("failed to read metadata length in '%s'"),
                             path);
        goto error;
    }

    if (len < 1 || len > 8192) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("length of metadata out of range"));
        goto error;
    }

    if (VIR_ALLOC_N(xml, len+1) < 0)
        goto error;

    if (saferead(fd, xml, len) != len) {
        virReportSystemError(errno, _("incomplete metadata in '%s'"), path);
        goto error;
    }
    xml[len] = '\0';

    if (!(def = virDomainDefParseString(xml, driver->caps, driver->xmlopt, NULL,
                                        VIR_DOMAIN_DEF_PARSE_INACTIVE |
                                        VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
        goto error;

    VIR_STEAL_PTR(*ret_def, def);
    return fd;

 error:
    virDomainDefFree(def);
    VIR_FORCE_CLOSE(fd);
    return -1;
}


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

    virCheckFlags(0, -1);

    if (dxml) {
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
        return -1;
2192
    }
2193 2194 2195 2196 2197 2198 2199 2200 2201

    if (!(privdom = testDomObjFromDomain(domain)))
        goto cleanup;

    if (virDomainObjCheckActive(privdom) < 0)
        goto cleanup;

    if (!testDomainSaveImageWrite(privconn, path, privdom->def))
        goto cleanup;
2202

J
Jiri Denemark 已提交
2203
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SAVED);
2204
    event = virDomainEventLifecycleNewFromObj(privdom,
2205 2206
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
2207

2208
    if (!privdom->persistent)
2209
        virDomainObjListRemove(privconn->domains, privdom);
2210

2211
    ret = 0;
2212
 cleanup:
2213
    virDomainObjEndAPI(&privdom);
2214
    virObjectEventStateQueue(privconn->eventState, event);
2215
    return ret;
2216 2217
}

2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229
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)
2230
{
2231
    testDriverPtr privconn = conn->privateData;
2232 2233
    int fd = -1;
    virDomainDefPtr def = NULL;
2234
    virDomainObjPtr dom = NULL;
2235
    virObjectEventPtr event = NULL;
2236
    int ret = -1;
2237

2238 2239
    virCheckFlags(0, -1);
    if (dxml) {
2240 2241
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
2242 2243 2244
        return -1;
    }

2245
    if ((fd = testDomainSaveImageOpen(privconn, path, &def)) < 0)
2246
        goto cleanup;
2247

2248
    if (testDomainGenerateIfnames(def) < 0)
2249
        goto cleanup;
2250
    if (!(dom = virDomainObjListAdd(privconn->domains,
2251
                                    def,
2252
                                    privconn->xmlopt,
2253 2254 2255
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
2256 2257
        goto cleanup;
    def = NULL;
2258

2259
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_RESTORED) < 0) {
2260
        if (!dom->persistent)
2261
            virDomainObjListRemove(privconn->domains, dom);
2262
        goto cleanup;
2263
    }
2264

2265
    event = virDomainEventLifecycleNewFromObj(dom,
2266 2267
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
2268
    ret = 0;
2269

2270
 cleanup:
2271
    virDomainDefFree(def);
2272
    VIR_FORCE_CLOSE(fd);
2273
    virDomainObjEndAPI(&dom);
2274
    virObjectEventStateQueue(privconn->eventState, event);
2275
    return ret;
2276 2277
}

2278 2279 2280 2281 2282 2283 2284
static int
testDomainRestore(virConnectPtr conn,
                  const char *path)
{
    return testDomainRestoreFlags(conn, path, NULL, 0);
}

2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320

static int
testDomainSaveImageDefineXML(virConnectPtr conn,
                             const char *path,
                             const char *dxml,
                             unsigned int flags)
{
    int ret = -1;
    int fd = -1;
    virDomainDefPtr def = NULL;
    virDomainDefPtr newdef = NULL;
    testDriverPtr privconn = conn->privateData;

    virCheckFlags(VIR_DOMAIN_SAVE_RUNNING |
                  VIR_DOMAIN_SAVE_PAUSED, -1);

    if ((fd = testDomainSaveImageOpen(privconn, path, &def)) < 0)
        goto cleanup;
    VIR_FORCE_CLOSE(fd);

    if ((newdef = virDomainDefParseString(dxml, privconn->caps, privconn->xmlopt, NULL,
                                          VIR_DOMAIN_DEF_PARSE_INACTIVE)) == NULL)
        goto cleanup;

    if (!testDomainSaveImageWrite(privconn, path, newdef))
        goto cleanup;

    ret = 0;

 cleanup:
    virDomainDefFree(def);
    virDomainDefFree(newdef);
    return ret;
}


2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344
static char *
testDomainSaveImageGetXMLDesc(virConnectPtr conn,
                              const char *path,
                              unsigned int flags)
{
    int fd = -1;
    char *ret = NULL;
    virDomainDefPtr def = NULL;
    testDriverPtr privconn = conn->privateData;

    virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL);

    if ((fd = testDomainSaveImageOpen(privconn, path, &def)) < 0)
        goto cleanup;

    ret = virDomainDefFormat(def, privconn->caps, VIR_DOMAIN_DEF_FORMAT_SECURE);

 cleanup:
    virDomainDefFree(def);
    VIR_FORCE_CLOSE(fd);
    return ret;
}


2345 2346 2347 2348
static int testDomainCoreDumpWithFormat(virDomainPtr domain,
                                        const char *to,
                                        unsigned int dumpformat,
                                        unsigned int flags)
2349
{
2350
    testDriverPtr privconn = domain->conn->privateData;
2351
    int fd = -1;
2352
    virDomainObjPtr privdom;
2353
    virObjectEventPtr event = NULL;
2354
    int ret = -1;
2355

E
Eric Blake 已提交
2356 2357
    virCheckFlags(VIR_DUMP_CRASH, -1);

2358

2359
    if (!(privdom = testDomObjFromDomain(domain)))
2360
        goto cleanup;
2361

2362
    if (virDomainObjCheckActive(privdom) < 0)
2363 2364
        goto cleanup;

2365
    if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
2366
        virReportSystemError(errno,
2367 2368
                             _("domain '%s' coredump: failed to open %s"),
                             domain->name, to);
2369
        goto cleanup;
2370
    }
2371
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
2372
        virReportSystemError(errno,
2373 2374
                             _("domain '%s' coredump: failed to write header to %s"),
                             domain->name, to);
2375
        goto cleanup;
2376
    }
2377
    if (VIR_CLOSE(fd) < 0) {
2378
        virReportSystemError(errno,
2379 2380
                             _("domain '%s' coredump: write failed: %s"),
                             domain->name, to);
2381
        goto cleanup;
2382
    }
2383

2384 2385 2386 2387 2388 2389 2390
    /* 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;
    }

2391
    if (flags & VIR_DUMP_CRASH) {
J
Jiri Denemark 已提交
2392
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_CRASHED);
2393
        event = virDomainEventLifecycleNewFromObj(privdom,
2394 2395
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
2396
        if (!privdom->persistent)
2397
            virDomainObjListRemove(privconn->domains, privdom);
2398
    }
2399

2400
    ret = 0;
2401
 cleanup:
2402
    VIR_FORCE_CLOSE(fd);
2403
    virDomainObjEndAPI(&privdom);
2404
    virObjectEventStateQueue(privconn->eventState, event);
2405
    return ret;
2406 2407
}

2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421

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)
{
2422 2423 2424
    char *ret;

    ignore_value(VIR_STRDUP(ret, "linux"));
2425
    return ret;
2426 2427
}

2428

2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441
static int
testDomainGetLaunchSecurityInfo(virDomainPtr domain ATTRIBUTE_UNUSED,
                                virTypedParameterPtr *params ATTRIBUTE_UNUSED,
                                int *nparams,
                                unsigned int flags)
{
    virCheckFlags(0, -1);

    *nparams = 0;
    return 0;
}


2442 2443
static unsigned long long
testDomainGetMaxMemory(virDomainPtr domain)
2444
{
2445
    virDomainObjPtr privdom;
2446
    unsigned long long ret = 0;
2447

2448 2449
    if (!(privdom = testDomObjFromDomain(domain)))
        return 0;
2450

2451
    ret = virDomainDefGetMemoryTotal(privdom->def);
2452

2453
    virDomainObjEndAPI(&privdom);
2454
    return ret;
2455 2456
}

2457 2458
static int testDomainSetMaxMemory(virDomainPtr domain,
                                  unsigned long memory)
2459
{
2460 2461
    virDomainObjPtr privdom;

2462 2463
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2464 2465

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

2468
    virDomainObjEndAPI(&privdom);
2469
    return 0;
2470 2471
}

E
Eric Blake 已提交
2472 2473 2474
static int testDomainSetMemoryFlags(virDomainPtr domain,
                                    unsigned long memory,
                                    unsigned int flags)
2475
{
2476
    virDomainObjPtr privdom;
2477
    int ret = -1;
2478

E
Eric Blake 已提交
2479 2480
    virCheckFlags(0, -1);

2481 2482
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2483

2484
    if (memory > virDomainDefGetMemoryTotal(privdom->def)) {
2485
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2486
        goto cleanup;
2487
    }
2488

2489
    privdom->def->mem.cur_balloon = memory;
2490 2491
    ret = 0;

2492
 cleanup:
2493
    virDomainObjEndAPI(&privdom);
2494
    return ret;
2495 2496
}

E
Eric Blake 已提交
2497 2498 2499 2500 2501 2502
static int testDomainSetMemory(virDomainPtr domain,
                               unsigned long memory)
{
    return testDomainSetMemoryFlags(domain, memory, 0);
}

2503 2504
static int
testDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
C
Cole Robinson 已提交
2505
{
2506 2507 2508 2509
    virDomainObjPtr vm;
    virDomainDefPtr def;
    int ret = -1;

2510 2511
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2512 2513
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

2514 2515
    if (!(vm = testDomObjFromDomain(domain)))
        return -1;
2516

2517
    if (!(def = virDomainObjGetOneDef(vm, flags)))
2518
        goto cleanup;
2519

2520 2521 2522
    if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
        ret = virDomainDefGetVcpusMax(def);
    else
2523
        ret = virDomainDefGetVcpus(def);
2524

2525
 cleanup:
2526
    virDomainObjEndAPI(&vm);
2527
    return ret;
C
Cole Robinson 已提交
2528 2529
}

2530 2531 2532
static int
testDomainGetMaxVcpus(virDomainPtr domain)
{
2533
    return testDomainGetVcpusFlags(domain, (VIR_DOMAIN_AFFECT_LIVE |
2534 2535 2536 2537 2538 2539 2540
                                            VIR_DOMAIN_VCPU_MAXIMUM));
}

static int
testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
                        unsigned int flags)
{
2541
    testDriverPtr driver = domain->conn->privateData;
2542
    virDomainObjPtr privdom = NULL;
2543
    virDomainDefPtr def;
2544
    virDomainDefPtr persistentDef;
C
Cole Robinson 已提交
2545 2546
    int ret = -1, maxvcpus;

2547 2548
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2549 2550
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

2551
    if ((maxvcpus = testConnectGetMaxVcpus(domain->conn, NULL)) < 0)
2552
        return -1;
2553 2554

    if (nrCpus > maxvcpus) {
2555
        virReportError(VIR_ERR_INVALID_ARG,
2556 2557
                       _("requested cpu amount exceeds maximum supported amount "
                         "(%d > %d)"), nrCpus, maxvcpus);
2558 2559
        return -1;
    }
2560

2561 2562
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2563

2564
    if (virDomainObjGetDefs(privdom, flags, &def, &persistentDef) < 0)
C
Cole Robinson 已提交
2565 2566
        goto cleanup;

2567
    if (def && virDomainDefGetVcpusMax(def) < nrCpus) {
2568 2569
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested cpu amount exceeds maximum (%d > %d)"),
2570
                       nrCpus, virDomainDefGetVcpusMax(def));
2571
        goto cleanup;
2572
    }
2573

2574 2575
    if (persistentDef &&
        !(flags & VIR_DOMAIN_VCPU_MAXIMUM) &&
2576
        virDomainDefGetVcpusMax(persistentDef) < nrCpus) {
2577 2578
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested cpu amount exceeds maximum (%d > %d)"),
2579
                       nrCpus, virDomainDefGetVcpusMax(persistentDef));
2580
        goto cleanup;
2581
    }
2582

2583 2584 2585
    if (def &&
        virDomainDefSetVcpus(def, nrCpus) < 0)
        goto cleanup;
2586

2587 2588
    if (persistentDef) {
        if (flags & VIR_DOMAIN_VCPU_MAXIMUM) {
2589 2590
            if (virDomainDefSetVcpusMax(persistentDef, nrCpus,
                                        driver->xmlopt) < 0)
2591
                goto cleanup;
2592
        } else {
2593 2594
            if (virDomainDefSetVcpus(persistentDef, nrCpus) < 0)
                goto cleanup;
2595
        }
2596
    }
2597

2598 2599
    ret = 0;

2600
 cleanup:
2601
    virDomainObjEndAPI(&privdom);
2602
    return ret;
2603 2604
}

2605
static int
2606
testDomainSetVcpus(virDomainPtr domain, unsigned int nrCpus)
2607
{
2608
    return testDomainSetVcpusFlags(domain, nrCpus, VIR_DOMAIN_AFFECT_LIVE);
2609 2610
}

C
Cole Robinson 已提交
2611 2612 2613 2614 2615 2616
static int testDomainGetVcpus(virDomainPtr domain,
                              virVcpuInfoPtr info,
                              int maxinfo,
                              unsigned char *cpumaps,
                              int maplen)
{
2617
    testDriverPtr privconn = domain->conn->privateData;
C
Cole Robinson 已提交
2618
    virDomainObjPtr privdom;
2619
    virDomainDefPtr def;
2620
    size_t i;
2621
    int hostcpus;
C
Cole Robinson 已提交
2622 2623 2624
    int ret = -1;
    struct timeval tv;
    unsigned long long statbase;
2625
    virBitmapPtr allcpumap = NULL;
C
Cole Robinson 已提交
2626

2627 2628
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
C
Cole Robinson 已提交
2629 2630

    if (!virDomainObjIsActive(privdom)) {
2631
        virReportError(VIR_ERR_OPERATION_INVALID,
2632
                       "%s", _("cannot list vcpus for an inactive domain"));
C
Cole Robinson 已提交
2633 2634 2635
        goto cleanup;
    }

2636
    def = privdom->def;
C
Cole Robinson 已提交
2637 2638

    if (gettimeofday(&tv, NULL) < 0) {
2639
        virReportSystemError(errno,
C
Cole Robinson 已提交
2640 2641 2642 2643 2644 2645 2646
                             "%s", _("getting time of day"));
        goto cleanup;
    }

    statbase = (tv.tv_sec * 1000UL * 1000UL) + tv.tv_usec;

    hostcpus = VIR_NODEINFO_MAXCPUS(privconn->nodeInfo);
2647 2648 2649 2650 2651
    if (!(allcpumap = virBitmapNew(hostcpus)))
        goto cleanup;

    virBitmapSetAll(allcpumap);

C
Cole Robinson 已提交
2652
    /* Clamp to actual number of vcpus */
2653 2654
    if (maxinfo > virDomainDefGetVcpus(privdom->def))
        maxinfo = virDomainDefGetVcpus(privdom->def);
C
Cole Robinson 已提交
2655

2656 2657
    memset(info, 0, sizeof(*info) * maxinfo);
    memset(cpumaps, 0, maxinfo * maplen);
C
Cole Robinson 已提交
2658

2659
    for (i = 0; i < maxinfo; i++) {
2660
        virDomainVcpuDefPtr vcpu = virDomainDefGetVcpu(def, i);
2661
        virBitmapPtr bitmap = NULL;
C
Cole Robinson 已提交
2662

2663 2664
        if (!vcpu->online)
            continue;
C
Cole Robinson 已提交
2665

2666 2667
        if (vcpu->cpumask)
            bitmap = vcpu->cpumask;
2668 2669 2670 2671
        else if (def->cpumask)
            bitmap = def->cpumask;
        else
            bitmap = allcpumap;
C
Cole Robinson 已提交
2672

2673 2674
        if (cpumaps)
            virBitmapToDataBuf(bitmap, VIR_GET_CPUMAP(cpumaps, maplen, i), maplen);
C
Cole Robinson 已提交
2675

2676 2677 2678
        info[i].number = i;
        info[i].state = VIR_VCPU_RUNNING;
        info[i].cpu = virBitmapLastSetBit(bitmap);
C
Cole Robinson 已提交
2679

2680 2681
        /* Fake an increasing cpu time value */
        info[i].cpuTime = statbase / 10;
C
Cole Robinson 已提交
2682 2683 2684
    }

    ret = maxinfo;
2685
 cleanup:
2686
    virBitmapFree(allcpumap);
2687
    virDomainObjEndAPI(&privdom);
C
Cole Robinson 已提交
2688 2689 2690
    return ret;
}

E
Eric Blake 已提交
2691 2692 2693 2694 2695
static int testDomainPinVcpuFlags(virDomainPtr domain,
                                  unsigned int vcpu,
                                  unsigned char *cpumap,
                                  int maplen,
                                  unsigned int flags)
C
Cole Robinson 已提交
2696
{
2697
    virDomainVcpuDefPtr vcpuinfo;
C
Cole Robinson 已提交
2698
    virDomainObjPtr privdom;
2699
    virDomainDefPtr def;
C
Cole Robinson 已提交
2700 2701
    int ret = -1;

E
Eric Blake 已提交
2702 2703
    virCheckFlags(0, -1);

2704 2705
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
C
Cole Robinson 已提交
2706

2707 2708
    def = privdom->def;

C
Cole Robinson 已提交
2709
    if (!virDomainObjIsActive(privdom)) {
2710
        virReportError(VIR_ERR_OPERATION_INVALID,
2711
                       "%s", _("cannot pin vcpus on an inactive domain"));
C
Cole Robinson 已提交
2712 2713 2714
        goto cleanup;
    }

2715 2716
    if (!(vcpuinfo = virDomainDefGetVcpu(def, vcpu)) ||
        !vcpuinfo->online) {
2717 2718 2719
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested vcpu '%d' is not present in the domain"),
                       vcpu);
C
Cole Robinson 已提交
2720 2721 2722
        goto cleanup;
    }

2723 2724 2725
    virBitmapFree(vcpuinfo->cpumask);

    if (!(vcpuinfo->cpumask = virBitmapNewData(cpumap, maplen)))
2726
        goto cleanup;
C
Cole Robinson 已提交
2727 2728

    ret = 0;
2729

2730
 cleanup:
2731
    virDomainObjEndAPI(&privdom);
C
Cole Robinson 已提交
2732 2733 2734
    return ret;
}

E
Eric Blake 已提交
2735 2736 2737 2738 2739 2740 2741 2742
static int testDomainPinVcpu(virDomainPtr domain,
                             unsigned int vcpu,
                             unsigned char *cpumap,
                             int maplen)
{
    return testDomainPinVcpuFlags(domain, vcpu, cpumap, maplen, 0);
}

2743 2744 2745 2746 2747 2748 2749
static int
testDomainGetVcpuPinInfo(virDomainPtr dom,
                        int ncpumaps,
                        unsigned char *cpumaps,
                        int maplen,
                        unsigned int flags)
{
2750
    testDriverPtr driver = dom->conn->privateData;
2751 2752
    virDomainObjPtr privdom;
    virDomainDefPtr def;
2753
    int ret = -1;
2754 2755 2756 2757 2758 2759 2760

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

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

2761 2762 2763
    ret = virDomainDefGetVcpuPinInfoHelper(def, maplen, ncpumaps, cpumaps,
                                           VIR_NODEINFO_MAXCPUS(driver->nodeInfo),
                                           NULL);
2764 2765 2766 2767 2768 2769

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

2770 2771 2772 2773 2774 2775 2776 2777 2778 2779
static int
testDomainRenameCallback(virDomainObjPtr privdom,
                         const char *new_name,
                         unsigned int flags,
                         void *opaque)
{
    testDriverPtr driver = opaque;
    virObjectEventPtr event_new = NULL;
    virObjectEventPtr event_old = NULL;
    int ret = -1;
2780
    VIR_AUTOFREE(char *) new_dom_name = NULL;
2781 2782 2783

    virCheckFlags(0, -1);

2784 2785 2786 2787 2788 2789
    if (strchr(new_name, '/')) {
        virReportError(VIR_ERR_XML_ERROR,
                       _("name %s cannot contain '/'"), new_name);
        return -1;
    }

2790 2791 2792 2793 2794 2795 2796 2797
    if (VIR_STRDUP(new_dom_name, new_name) < 0)
        goto cleanup;

    event_old = virDomainEventLifecycleNewFromObj(privdom,
                                                  VIR_DOMAIN_EVENT_UNDEFINED,
                                                  VIR_DOMAIN_EVENT_UNDEFINED_RENAMED);

    /* Switch name in domain definition. */
2798 2799
    VIR_FREE(privdom->def->name);
    VIR_STEAL_PTR(privdom->def->name, new_dom_name);
2800 2801 2802 2803 2804 2805 2806

    event_new = virDomainEventLifecycleNewFromObj(privdom,
                                                  VIR_DOMAIN_EVENT_DEFINED,
                                                  VIR_DOMAIN_EVENT_DEFINED_RENAMED);
    ret = 0;

 cleanup:
2807 2808
    virObjectEventStateQueue(driver->eventState, event_old);
    virObjectEventStateQueue(driver->eventState, event_new);
2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855
    return ret;
}

static int
testDomainRename(virDomainPtr dom,
                 const char *new_name,
                 unsigned int flags)
{
    testDriverPtr driver = dom->conn->privateData;
    virDomainObjPtr privdom = NULL;
    int ret = -1;

    virCheckFlags(0, ret);

    if (!(privdom = testDomObjFromDomain(dom)))
        goto cleanup;

    if (virDomainObjIsActive(privdom)) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot rename active domain"));
        goto cleanup;
    }

    if (!privdom->persistent) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot rename a transient domain"));
        goto cleanup;
    }

    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_SHUTOFF) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain has to be shutoff before renaming"));
        goto cleanup;
    }

    if (virDomainObjListRename(driver->domains, privdom, new_name, flags,
                               testDomainRenameCallback, driver) < 0)
        goto cleanup;

    /* Success, domain has been renamed. */
    ret = 0;

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

2856
static char *testDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
2857
{
2858
    testDriverPtr privconn = domain->conn->privateData;
2859
    virDomainDefPtr def;
2860
    virDomainObjPtr privdom;
2861 2862
    char *ret = NULL;

2863
    virCheckFlags(VIR_DOMAIN_XML_COMMON_FLAGS, NULL);
2864

2865 2866
    if (!(privdom = testDomObjFromDomain(domain)))
        return NULL;
2867

2868 2869
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
2870

2871 2872
    ret = virDomainDefFormat(def, privconn->caps,
                             virDomainDefFormatConvertXMLFlags(flags));
2873

2874
    virDomainObjEndAPI(&privdom);
2875
    return ret;
2876
}
2877

2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920

#define TEST_SET_PARAM(index, name, type, value) \
    if (index < *nparams && \
        virTypedParameterAssign(&params[index], name, type, value) < 0) \
        goto cleanup

static int
testDomainGetMemoryParameters(virDomainPtr dom,
                              virTypedParameterPtr params,
                              int *nparams,
                              unsigned int flags)
{
    int ret = -1;
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
                  VIR_TYPED_PARAM_STRING_OKAY, -1);

    if ((*nparams) == 0) {
        *nparams = 3;
        return 0;
    }

    if (!(vm = testDomObjFromDomain(dom)))
        goto cleanup;

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

    TEST_SET_PARAM(0, VIR_DOMAIN_MEMORY_HARD_LIMIT, VIR_TYPED_PARAM_ULLONG, def->mem.hard_limit);
    TEST_SET_PARAM(1, VIR_DOMAIN_MEMORY_SOFT_LIMIT, VIR_TYPED_PARAM_ULLONG, def->mem.soft_limit);
    TEST_SET_PARAM(2, VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT, VIR_TYPED_PARAM_ULLONG, def->mem.swap_hard_limit);

    if (*nparams > 3)
        *nparams = 3;

    ret = 0;
 cleanup:
    virDomainObjEndAPI(&vm);
    return ret;
}
2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965


static int
testDomainGetNumaParameters(virDomainPtr dom,
                            virTypedParameterPtr params,
                            int *nparams,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    virDomainNumatuneMemMode mode = VIR_DOMAIN_NUMATUNE_MEM_STRICT;
    VIR_AUTOFREE(char *) nodeset = NULL;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
                  VIR_TYPED_PARAM_STRING_OKAY, -1);

    if ((*nparams) == 0) {
        *nparams = 2;
        return 0;
    }

    if (!(vm = testDomObjFromDomain(dom)))
        goto cleanup;

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

    ignore_value(virDomainNumatuneGetMode(def->numa, -1, &mode));
    nodeset = virDomainNumatuneFormatNodeset(def->numa, NULL, -1);

    TEST_SET_PARAM(0, VIR_DOMAIN_NUMA_MODE, VIR_TYPED_PARAM_INT, mode);
    TEST_SET_PARAM(1, VIR_DOMAIN_NUMA_NODESET, VIR_TYPED_PARAM_STRING, nodeset);

    nodeset = NULL;

    if (*nparams > 2)
        *nparams = 2;

    ret = 0;
 cleanup:
    virDomainObjEndAPI(&vm);
    return ret;
}
2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 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 3016 3017 3018 3019 3020 3021 3022


static int
testDomainGetInterfaceParameters(virDomainPtr dom,
                                 const char *device,
                                 virTypedParameterPtr params,
                                 int *nparams,
                                 unsigned int flags)
{
    virNetDevBandwidthRate in = {0};
    virNetDevBandwidthRate out = {0};
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    virDomainNetDefPtr net = NULL;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
                  VIR_TYPED_PARAM_STRING_OKAY, -1);

    if ((*nparams) == 0) {
        *nparams = 7;
        return 0;
    }

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

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

    if (!(net = virDomainNetFind(def, device)))
        goto cleanup;

    if (net->bandwidth) {
        if (net->bandwidth->in)
            in = *net->bandwidth->in;
        if (net->bandwidth->out)
            out = *net->bandwidth->out;
    }

    TEST_SET_PARAM(0, VIR_DOMAIN_BANDWIDTH_IN_AVERAGE, VIR_TYPED_PARAM_UINT, in.average);
    TEST_SET_PARAM(1, VIR_DOMAIN_BANDWIDTH_IN_PEAK, VIR_TYPED_PARAM_UINT, in.peak);
    TEST_SET_PARAM(2, VIR_DOMAIN_BANDWIDTH_IN_BURST, VIR_TYPED_PARAM_UINT, in.burst);
    TEST_SET_PARAM(3, VIR_DOMAIN_BANDWIDTH_IN_FLOOR, VIR_TYPED_PARAM_UINT, in.floor);
    TEST_SET_PARAM(4, VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE, VIR_TYPED_PARAM_UINT, out.average);
    TEST_SET_PARAM(5, VIR_DOMAIN_BANDWIDTH_OUT_PEAK, VIR_TYPED_PARAM_UINT, out.peak);
    TEST_SET_PARAM(6, VIR_DOMAIN_BANDWIDTH_OUT_BURST, VIR_TYPED_PARAM_UINT, out.burst);

    if (*nparams > 7)
        *nparams = 7;

    ret = 0;
 cleanup:
    virDomainObjEndAPI(&vm);
    return ret;
}
3023 3024 3025
#undef TEST_SET_PARAM


3026 3027
static int testConnectNumOfDefinedDomains(virConnectPtr conn)
{
3028
    testDriverPtr privconn = conn->privateData;
3029

3030
    return virDomainObjListNumOfDomains(privconn->domains, false, NULL, NULL);
3031 3032
}

3033 3034
static int testConnectListDefinedDomains(virConnectPtr conn,
                                         char **const names,
3035 3036
                                         int maxnames)
{
3037
    testDriverPtr privconn = conn->privateData;
3038 3039

    memset(names, 0, sizeof(*names)*maxnames);
3040 3041
    return virDomainObjListGetInactiveNames(privconn->domains, names, maxnames,
                                            NULL, NULL);
3042 3043
}

3044 3045 3046
static virDomainPtr testDomainDefineXMLFlags(virConnectPtr conn,
                                             const char *xml,
                                             unsigned int flags)
3047
{
3048
    testDriverPtr privconn = conn->privateData;
3049
    virDomainPtr ret = NULL;
3050
    virDomainDefPtr def;
3051
    virDomainObjPtr dom = NULL;
3052
    virObjectEventPtr event = NULL;
3053
    virDomainDefPtr oldDef = NULL;
3054 3055 3056
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;

    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
3057

3058
    if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
3059
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
3060

3061
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
3062
                                       NULL, parse_flags)) == NULL)
3063
        goto cleanup;
3064

3065 3066 3067
    if (virXMLCheckIllegalChars("name", def->name, "\n") < 0)
        goto cleanup;

3068
    if (testDomainGenerateIfnames(def) < 0)
3069
        goto cleanup;
3070
    if (!(dom = virDomainObjListAdd(privconn->domains,
3071
                                    def,
3072
                                    privconn->xmlopt,
3073 3074
                                    0,
                                    &oldDef)))
3075
        goto cleanup;
3076
    def = NULL;
3077
    dom->persistent = 1;
3078

3079
    event = virDomainEventLifecycleNewFromObj(dom,
3080
                                     VIR_DOMAIN_EVENT_DEFINED,
3081
                                     !oldDef ?
3082 3083
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
3084

3085
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
3086

3087
 cleanup:
3088
    virDomainDefFree(def);
3089
    virDomainDefFree(oldDef);
3090
    virDomainObjEndAPI(&dom);
3091
    virObjectEventStateQueue(privconn->eventState, event);
3092
    return ret;
3093 3094
}

3095 3096 3097 3098 3099 3100
static virDomainPtr
testDomainDefineXML(virConnectPtr conn, const char *xml)
{
    return testDomainDefineXMLFlags(conn, xml, 0);
}

3101 3102 3103 3104 3105 3106
static char *testDomainGetMetadata(virDomainPtr dom,
                                   int type,
                                   const char *uri,
                                   unsigned int flags)
{
    virDomainObjPtr privdom;
3107
    char *ret;
3108 3109 3110 3111

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, NULL);

3112 3113
    if (!(privdom = testDomObjFromDomain(dom)))
        return NULL;
3114

3115
    ret = virDomainObjGetMetadata(privdom, type, uri, flags);
3116

3117
    virDomainObjEndAPI(&privdom);
3118 3119 3120 3121 3122 3123 3124 3125 3126 3127
    return ret;
}

static int testDomainSetMetadata(virDomainPtr dom,
                                 int type,
                                 const char *metadata,
                                 const char *key,
                                 const char *uri,
                                 unsigned int flags)
{
3128
    testDriverPtr privconn = dom->conn->privateData;
3129
    virDomainObjPtr privdom;
3130
    int ret;
3131 3132 3133 3134

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

3135 3136
    if (!(privdom = testDomObjFromDomain(dom)))
        return -1;
3137 3138 3139

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

3142 3143 3144
    if (ret == 0) {
        virObjectEventPtr ev = NULL;
        ev = virDomainEventMetadataChangeNewFromObj(privdom, type, uri);
3145
        virObjectEventStateQueue(privconn->eventState, ev);
3146 3147
    }

3148
    virDomainObjEndAPI(&privdom);
3149 3150 3151
    return ret;
}

3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185
static int
testDomainSendProcessSignal(virDomainPtr dom,
                            long long pid_value,
                            unsigned int signum,
                            unsigned int flags)
{
    int ret = -1;
    virDomainObjPtr vm = NULL;

    virCheckFlags(0, -1);

    if (pid_value != 1) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("only sending a signal to pid 1 is supported"));
        return -1;
    }

    if (signum >= VIR_DOMAIN_PROCESS_SIGNAL_LAST) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("signum value %d is out of range"),
                       signum);
        return -1;
    }

    if (!(vm = testDomObjFromDomain(dom)))
        goto cleanup;

    /* do nothing */
    ret = 0;

 cleanup:
    virDomainObjEndAPI(&vm);
    return ret;
}
3186

3187 3188
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
3189 3190
                                      int startCell, int maxCells)
{
3191
    testDriverPtr privconn = conn->privateData;
3192 3193
    int cell;
    size_t i;
3194
    int ret = -1;
3195

3196
    virObjectLock(privconn);
3197
    if (startCell >= privconn->numCells) {
3198 3199
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("Range exceeds available cells"));
3200
        goto cleanup;
3201 3202
    }

3203 3204 3205 3206
    for (cell = startCell, i = 0;
         (cell < privconn->numCells && i < maxCells);
         ++cell, ++i) {
        freemems[i] = privconn->cells[cell].mem;
3207
    }
3208
    ret = i;
3209

3210
 cleanup:
3211
    virObjectUnlock(privconn);
3212
    return ret;
3213 3214
}

3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260
#define TEST_NB_CPU_STATS 4

static int
testNodeGetCPUStats(virConnectPtr conn ATTRIBUTE_UNUSED,
                    int cpuNum ATTRIBUTE_UNUSED,
                    virNodeCPUStatsPtr params,
                    int *nparams,
                    unsigned int flags)
{
    size_t i = 0;

    virCheckFlags(0, -1);

    if (params == NULL) {
        *nparams = TEST_NB_CPU_STATS;
        return 0;
    }

    for (i = 0; i < *nparams && i < 4; i++) {
        switch (i) {
        case 0:
            if (virHostCPUStatsAssign(&params[i],
                                      VIR_NODE_CPU_STATS_USER, 9797400000) < 0)
                return -1;
            break;
        case 1:
            if (virHostCPUStatsAssign(&params[i],
                                      VIR_NODE_CPU_STATS_KERNEL, 34678723400000) < 0)
                return -1;
            break;
        case 2:
            if (virHostCPUStatsAssign(&params[i],
                                      VIR_NODE_CPU_STATS_IDLE, 87264900000) < 0)
                return -1;
            break;
        case 3:
            if (virHostCPUStatsAssign(&params[i],
                                      VIR_NODE_CPU_STATS_IOWAIT, 763600000) < 0)
                return -1;
            break;
        }
    }

    *nparams = i;
    return 0;
}
3261

3262 3263 3264 3265 3266 3267 3268
static unsigned long long
testNodeGetFreeMemory(virConnectPtr conn)
{
    testDriverPtr privconn = conn->privateData;
    unsigned int freeMem = 0;
    size_t i;

3269
    virObjectLock(privconn);
3270 3271 3272 3273

    for (i = 0; i < privconn->numCells; i++)
        freeMem += privconn->cells[i].freeMem;

3274
    virObjectUnlock(privconn);
3275 3276 3277
    return freeMem;
}

3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301
static int
testNodeGetFreePages(virConnectPtr conn ATTRIBUTE_UNUSED,
                     unsigned int npages,
                     unsigned int *pages ATTRIBUTE_UNUSED,
                     int startCell ATTRIBUTE_UNUSED,
                     unsigned int cellCount,
                     unsigned long long *counts,
                     unsigned int flags)
{
    size_t i = 0, j = 0;
    int x = 6;

    virCheckFlags(0, -1);

    for (i = 0; i < cellCount; i++) {
        for (j = 0; j < npages; j++) {
            x = x * 2 + 7;
            counts[(i * npages) +  j] = x;
        }
    }

    return 0;
}

3302 3303
static int testDomainCreateWithFlags(virDomainPtr domain, unsigned int flags)
{
3304
    testDriverPtr privconn = domain->conn->privateData;
3305
    virDomainObjPtr privdom;
3306
    virObjectEventPtr event = NULL;
3307
    int ret = -1;
3308

3309 3310
    virCheckFlags(0, -1);

3311
    virObjectLock(privconn);
3312

3313
    if (!(privdom = testDomObjFromDomain(domain)))
3314
        goto cleanup;
3315

J
Jiri Denemark 已提交
3316
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_SHUTOFF) {
3317 3318
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Domain '%s' is already running"), domain->name);
3319
        goto cleanup;
3320 3321
    }

3322
    if (testDomainStartState(privconn, privdom,
J
Jiri Denemark 已提交
3323
                             VIR_DOMAIN_RUNNING_BOOTED) < 0)
3324 3325 3326
        goto cleanup;
    domain->id = privdom->def->id;

3327
    event = virDomainEventLifecycleNewFromObj(privdom,
3328 3329
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
3330
    ret = 0;
3331

3332
 cleanup:
3333
    virDomainObjEndAPI(&privdom);
3334
    virObjectEventStateQueue(privconn->eventState, event);
3335
    virObjectUnlock(privconn);
3336
    return ret;
3337 3338
}

3339 3340
static int testDomainCreate(virDomainPtr domain)
{
3341 3342 3343
    return testDomainCreateWithFlags(domain, 0);
}

3344 3345 3346
static int testDomainUndefineFlags(virDomainPtr domain,
                                   unsigned int flags)
{
3347
    testDriverPtr privconn = domain->conn->privateData;
3348
    virDomainObjPtr privdom;
3349
    virObjectEventPtr event = NULL;
3350
    int nsnapshots;
3351
    int ret = -1;
3352

3353 3354
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
                  VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
3355

3356

3357
    if (!(privdom = testDomObjFromDomain(domain)))
3358
        goto cleanup;
3359

C
Cole Robinson 已提交
3360 3361 3362 3363 3364 3365 3366 3367
    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;
    }

3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385
    /* 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. */
    }

3386
    event = virDomainEventLifecycleNewFromObj(privdom,
3387 3388
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
C
Cole Robinson 已提交
3389 3390
    privdom->hasManagedSave = false;

3391
    if (virDomainObjIsActive(privdom))
3392
        privdom->persistent = 0;
3393
    else
3394
        virDomainObjListRemove(privconn->domains, privdom);
3395

3396
    ret = 0;
3397

3398
 cleanup:
3399
    virDomainObjEndAPI(&privdom);
3400
    virObjectEventStateQueue(privconn->eventState, event);
3401
    return ret;
3402 3403
}

3404 3405 3406 3407 3408
static int testDomainUndefine(virDomainPtr domain)
{
    return testDomainUndefineFlags(domain, 0);
}

3409 3410 3411
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
3412 3413
    virDomainObjPtr privdom;

3414 3415
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3416

3417
    *autostart = privdom->autostart;
3418

3419
    virDomainObjEndAPI(&privdom);
3420
    return 0;
3421 3422 3423 3424 3425 3426
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
3427 3428
    virDomainObjPtr privdom;

3429 3430
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3431

3432
    privdom->autostart = autostart ? 1 : 0;
3433

3434
    virDomainObjEndAPI(&privdom);
3435
    return 0;
3436
}
3437

3438 3439 3440 3441 3442 3443 3444 3445
static int testDomainGetDiskErrors(virDomainPtr dom,
                                   virDomainDiskErrorPtr errors,
                                   unsigned int maxerrors,
                                   unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;
    size_t i;
3446
    size_t nerrors = 0;
3447 3448 3449 3450

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(dom)))
3451
        return -1;
3452 3453 3454 3455

    if (virDomainObjCheckActive(vm) < 0)
        goto cleanup;

3456 3457
    nerrors = MIN(vm->def->ndisks, maxerrors);

3458
    if (errors) {
3459 3460 3461 3462
        /* sanitize input */
        memset(errors, 0, sizeof(virDomainDiskError) * nerrors);

        for (i = 0; i < nerrors; i++) {
3463 3464
            if (VIR_STRDUP(errors[i].disk, vm->def->disks[i]->dst) < 0)
                goto cleanup;
3465
            errors[i].error = (i % (VIR_DOMAIN_DISK_ERROR_LAST - 1)) + 1;
3466 3467 3468 3469 3470 3471 3472 3473
        }
        ret = i;
    } else {
        ret = vm->def->ndisks;
    }

 cleanup:
    if (ret < 0) {
3474
        for (i = 0; i < nerrors; i++)
3475 3476
            VIR_FREE(errors[i].disk);
    }
3477
    virDomainObjEndAPI(&vm);
3478 3479 3480
    return ret;
}

3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548


static int
testDomainGetFSInfo(virDomainPtr dom,
                    virDomainFSInfoPtr **info,
                    unsigned int flags)
{
    size_t i;
    virDomainObjPtr vm;
    virDomainFSInfoPtr *info_ret = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

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

    if (virDomainObjCheckActive(vm) < 0)
        goto cleanup;

    *info = NULL;

    for (i = 0; i < vm->def->ndisks; i++) {
        if (vm->def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
            char *name = vm->def->disks[i]->dst;

            if (VIR_ALLOC_N(info_ret, 2) < 0)
                goto cleanup;

            if (VIR_ALLOC(info_ret[0]) < 0 ||
                VIR_ALLOC(info_ret[0]->devAlias) < 0 ||
                VIR_STRDUP(info_ret[0]->mountpoint, "/") < 0 ||
                VIR_STRDUP(info_ret[0]->fstype, "ext4") < 0 ||
                VIR_STRDUP(info_ret[0]->devAlias[0], name) < 0 ||
                virAsprintf(&info_ret[0]->name, "%s1", name) < 0)
                goto cleanup;

            if (VIR_ALLOC(info_ret[1]) < 0 ||
                VIR_ALLOC(info_ret[1]->devAlias) < 0 ||
                VIR_STRDUP(info_ret[1]->mountpoint, "/boot") < 0 ||
                VIR_STRDUP(info_ret[1]->fstype, "ext4") < 0 ||
                VIR_STRDUP(info_ret[1]->devAlias[0], name) < 0 ||
                virAsprintf(&info_ret[1]->name, "%s2", name) < 0)
                goto cleanup;

            info_ret[0]->ndevAlias = info_ret[1]->ndevAlias = 1;

            VIR_STEAL_PTR(*info, info_ret);

            ret = 2;
            goto cleanup;
        }
    }

    ret = 0;

 cleanup:
    if (info_ret) {
        virDomainFSInfoFree(info_ret[0]);
        virDomainFSInfoFree(info_ret[1]);
        VIR_FREE(info_ret);
    }

    virDomainObjEndAPI(&vm);
    return ret;
}


3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611
static int
testDomainSetPerfEvents(virDomainPtr dom,
                        virTypedParameterPtr params,
                        int nparams,
                        unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    size_t i;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

    if (virTypedParamsValidate(params, nparams,
                               VIR_PERF_PARAM_CMT, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_MBMT, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_MBML, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_CPU_CYCLES, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_INSTRUCTIONS, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_CACHE_REFERENCES, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_CACHE_MISSES, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_BRANCH_INSTRUCTIONS, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_BRANCH_MISSES, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_BUS_CYCLES, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_STALLED_CYCLES_FRONTEND, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_STALLED_CYCLES_BACKEND, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_REF_CPU_CYCLES, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_CPU_CLOCK, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_TASK_CLOCK, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_PAGE_FAULTS, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_CONTEXT_SWITCHES, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_CPU_MIGRATIONS, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_PAGE_FAULTS_MIN, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_PAGE_FAULTS_MAJ, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_ALIGNMENT_FAULTS, VIR_TYPED_PARAM_BOOLEAN,
                               VIR_PERF_PARAM_EMULATION_FAULTS, VIR_TYPED_PARAM_BOOLEAN,
                               NULL) < 0)
        return -1;

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

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

    for (i = 0; i < nparams; i++) {
        virTypedParameterPtr param = &params[i];
        virPerfEventType type = virPerfEventTypeFromString(param->field);

        if (param->value.b)
            def->perf.events[type] = VIR_TRISTATE_BOOL_YES;
        else
            def->perf.events[type] = VIR_TRISTATE_BOOL_NO;
    }

    ret = 0;
 cleanup:
    virDomainObjEndAPI(&vm);
    return ret;
}


3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654
static int
testDomainGetPerfEvents(virDomainPtr dom,
                        virTypedParameterPtr *params,
                        int *nparams,
                        unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    virTypedParameterPtr par = NULL;
    size_t i;
    int maxpar = 0;
    int npar = 0;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
                  VIR_TYPED_PARAM_STRING_OKAY, -1);

    if (!(vm = testDomObjFromDomain(dom)))
        goto cleanup;

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

    for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
        if (virTypedParamsAddBoolean(&par, &npar, &maxpar,
                                     virPerfEventTypeToString(i),
                                     def->perf.events[i] == VIR_TRISTATE_BOOL_YES) < 0)
            goto cleanup;
    }

    VIR_STEAL_PTR(*params, par);
    *nparams = npar;
    npar = 0;

    ret = 0;
 cleanup:
    virDomainObjEndAPI(&vm);
    virTypedParamsFree(par, npar);
    return ret;
}


3655
static char *testDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED,
3656 3657
                                        int *nparams)
{
3658 3659
    char *type = NULL;

3660 3661 3662
    if (nparams)
        *nparams = 1;

3663
    ignore_value(VIR_STRDUP(type, "fair"));
3664

3665 3666 3667
    return type;
}

3668
static int
3669 3670 3671 3672
testDomainGetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int *nparams,
                                      unsigned int flags)
3673
{
3674
    virDomainObjPtr privdom;
3675
    int ret = -1;
3676

3677 3678
    virCheckFlags(0, -1);

3679 3680
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3681

3682 3683
    if (virTypedParameterAssign(params, VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, 50) < 0)
3684
        goto cleanup;
3685 3686
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
3687 3688

    *nparams = 1;
3689 3690
    ret = 0;

3691
 cleanup:
3692
    virDomainObjEndAPI(&privdom);
3693
    return ret;
3694
}
3695

3696
static int
3697 3698 3699
testDomainGetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int *nparams)
3700
{
3701
    return testDomainGetSchedulerParametersFlags(domain, params, nparams, 0);
3702
}
3703

3704
static int
3705 3706 3707 3708
testDomainSetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int nparams,
                                      unsigned int flags)
3709
{
3710
    virDomainObjPtr privdom;
3711 3712
    int ret = -1;
    size_t i;
3713

3714
    virCheckFlags(0, -1);
3715 3716 3717 3718
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
3719
        return -1;
3720

3721 3722
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3723

3724
    for (i = 0; i < nparams; i++) {
3725 3726 3727
        if (STREQ(params[i].field, VIR_DOMAIN_SCHEDULER_WEIGHT)) {
            /* XXX */
            /*privdom->weight = params[i].value.ui;*/
3728
        }
3729
    }
3730

3731 3732
    ret = 0;

3733
    virDomainObjEndAPI(&privdom);
3734
    return ret;
3735 3736
}

3737
static int
3738 3739 3740
testDomainSetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int nparams)
3741
{
3742
    return testDomainSetSchedulerParametersFlags(domain, params, nparams, 0);
3743 3744
}

3745 3746
static int testDomainBlockStats(virDomainPtr domain,
                                const char *path,
3747
                                virDomainBlockStatsPtr stats)
3748 3749 3750 3751
{
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
3752
    int ret = -1;
3753

3754 3755 3756 3757 3758 3759
    if (!*path) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("summary statistics are not supported yet"));
        return ret;
    }

3760 3761
    if (!(privdom = testDomObjFromDomain(domain)))
        return ret;
3762

3763
    if (virDomainObjCheckActive(privdom) < 0)
3764 3765
        goto error;

3766
    if (virDomainDiskIndexByName(privdom->def, path, false) < 0) {
3767 3768
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path: %s"), path);
3769 3770 3771 3772
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
3773
        virReportSystemError(errno,
3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786
                             "%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;
3787
 error:
3788
    virDomainObjEndAPI(&privdom);
3789 3790 3791
    return ret;
}

3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836

static int
testDomainInterfaceAddressFromNet(testDriverPtr driver,
                                  const virDomainNetDef *net,
                                  size_t addr_offset,
                                  virDomainInterfacePtr iface)
{
    virSocketAddr addr;
    virNetworkObjPtr net_obj = NULL;
    virNetworkDefPtr net_def = NULL;
    int ret = -1;

    if (!(net_obj = testNetworkObjFindByName(driver, net->data.network.name)))
        return -1;

    net_def = virNetworkObjGetDef(net_obj);

    iface->addrs[0].prefix = virSocketAddrGetIPPrefix(&net_def->ips->address,
                                                      &net_def->ips->netmask,
                                                      net_def->ips->prefix);

    if (net_def->ips->nranges > 0)
        addr = net_def->ips->ranges[0].start;
    else
        addr = net_def->ips->address;

    if (net_def->ips->family && STREQ(net_def->ips->family, "ipv6")) {
        iface->addrs[0].type = VIR_IP_ADDR_TYPE_IPV6;
        addr.data.inet6.sin6_addr.s6_addr[15] += addr_offset;
    } else {
        iface->addrs[0].type = VIR_IP_ADDR_TYPE_IPV4;
        addr.data.inet4.sin_addr.s_addr = \
            htonl(ntohl(addr.data.inet4.sin_addr.s_addr) + addr_offset);
    }

    if (!(iface->addrs[0].addr = virSocketAddrFormat(&addr)))
        goto cleanup;

    ret = 0;
 cleanup:
    virNetworkObjEndAPI(&net_obj);
    return ret;
}


3837 3838 3839
static int
testDomainInterfaceAddresses(virDomainPtr dom,
                             virDomainInterfacePtr **ifaces,
3840
                             unsigned int source,
3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852
                             unsigned int flags)
{
    size_t i;
    size_t ifaces_count = 0;
    int ret = -1;
    char macaddr[VIR_MAC_STRING_BUFLEN];
    virDomainObjPtr vm = NULL;
    virDomainInterfacePtr iface = NULL;
    virDomainInterfacePtr *ifaces_ret = NULL;

    virCheckFlags(0, -1);

3853 3854 3855 3856 3857 3858 3859
    if (source >= VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LAST) {
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
                       _("Unknown IP address data source %d"),
                       source);
        return -1;
    }

3860 3861 3862 3863 3864 3865 3866 3867 3868 3869
    if (!(vm = testDomObjFromDomain(dom)))
        goto cleanup;

    if (virDomainObjCheckActive(vm) < 0)
        goto cleanup;

    if (VIR_ALLOC_N(ifaces_ret, vm->def->nnets) < 0)
        goto cleanup;

    for (i = 0; i < vm->def->nnets; i++) {
3870 3871
        const virDomainNetDef *net = vm->def->nets[i];

3872 3873 3874
        if (VIR_ALLOC(iface) < 0)
            goto cleanup;

3875
        if (VIR_STRDUP(iface->name, net->ifname) < 0)
3876 3877
            goto cleanup;

3878
        virMacAddrFormat(&net->mac, macaddr);
3879 3880 3881 3882 3883
        if (VIR_STRDUP(iface->hwaddr, macaddr) < 0)
            goto cleanup;

        if (VIR_ALLOC(iface->addrs) < 0)
            goto cleanup;
3884
        iface->naddrs = 1;
3885

3886 3887 3888
        if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
            /* try using different addresses per different inf and domain */
            const size_t addr_offset = 20 * (vm->def->id - 1) + i + 1;
3889

3890 3891 3892 3893 3894 3895 3896 3897 3898 3899
            if (testDomainInterfaceAddressFromNet(dom->conn->privateData,
                                                  net, addr_offset, iface) < 0)
                goto cleanup;
        } else {
            iface->addrs[0].type = VIR_IP_ADDR_TYPE_IPV4;
            iface->addrs[0].prefix = 24;
            if (virAsprintf(&iface->addrs[0].addr, "192.168.0.%zu", 1 + i) < 0)
                goto cleanup;

        }
3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919

        VIR_APPEND_ELEMENT_INPLACE(ifaces_ret, ifaces_count, iface);
    }

    VIR_STEAL_PTR(*ifaces, ifaces_ret);
    ret = ifaces_count;

 cleanup:
    virDomainObjEndAPI(&vm);

    if (ifaces_ret) {
        for (i = 0; i < ifaces_count; i++)
            virDomainInterfaceFree(ifaces_ret[i]);
    }
    virDomainInterfaceFree(iface);

    VIR_FREE(ifaces_ret);
    return ret;
}

3920 3921 3922 3923
static int
testDomainInterfaceStats(virDomainPtr domain,
                         const char *device,
                         virDomainInterfaceStatsPtr stats)
3924 3925 3926 3927
{
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
M
Michal Privoznik 已提交
3928 3929 3930
    virDomainNetDefPtr net = NULL;
    int ret = -1;

3931

3932 3933
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
3934

3935
    if (virDomainObjCheckActive(privdom) < 0)
3936 3937
        goto error;

3938
    if (!(net = virDomainNetFind(privdom->def, device)))
3939 3940 3941
        goto error;

    if (gettimeofday(&tv, NULL) < 0) {
3942
        virReportSystemError(errno,
3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958
                             "%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;
3959
 error:
3960
    virDomainObjEndAPI(&privdom);
3961 3962 3963
    return ret;
}

3964

3965 3966 3967 3968
static virNetworkObjPtr
testNetworkObjFindByUUID(testDriverPtr privconn,
                         const unsigned char *uuid)
{
3969
    virNetworkObjPtr obj;
3970 3971
    char uuidstr[VIR_UUID_STRING_BUFLEN];

3972
    if (!(obj = virNetworkObjFindByUUID(privconn->networks, uuid))) {
3973 3974 3975 3976 3977 3978
        virUUIDFormat(uuid, uuidstr);
        virReportError(VIR_ERR_NO_NETWORK,
                       _("no network with matching uuid '%s'"),
                       uuidstr);
    }

3979
    return obj;
3980 3981 3982
}


3983 3984 3985
static virNetworkPtr
testNetworkLookupByUUID(virConnectPtr conn,
                        const unsigned char *uuid)
3986
{
3987
    testDriverPtr privconn = conn->privateData;
3988
    virNetworkObjPtr obj;
3989
    virNetworkDefPtr def;
3990
    virNetworkPtr net = NULL;
3991

3992
    if (!(obj = testNetworkObjFindByUUID(privconn, uuid)))
3993
        goto cleanup;
3994
    def = virNetworkObjGetDef(obj);
3995

3996
    net = virGetNetwork(conn, def->name, def->uuid);
3997

3998
 cleanup:
3999 4000
    virNetworkObjEndAPI(&obj);
    return net;
4001
}
4002

4003 4004 4005 4006 4007

static virNetworkObjPtr
testNetworkObjFindByName(testDriverPtr privconn,
                         const char *name)
{
4008
    virNetworkObjPtr obj;
4009

4010
    if (!(obj = virNetworkObjFindByName(privconn->networks, name)))
4011 4012 4013 4014
        virReportError(VIR_ERR_NO_NETWORK,
                       _("no network with matching name '%s'"),
                       name);

4015
    return obj;
4016 4017 4018
}


4019 4020 4021
static virNetworkPtr
testNetworkLookupByName(virConnectPtr conn,
                        const char *name)
4022
{
4023
    testDriverPtr privconn = conn->privateData;
4024
    virNetworkObjPtr obj;
4025
    virNetworkDefPtr def;
4026
    virNetworkPtr net = NULL;
4027

4028
    if (!(obj = testNetworkObjFindByName(privconn, name)))
4029
        goto cleanup;
4030
    def = virNetworkObjGetDef(obj);
4031

4032
    net = virGetNetwork(conn, def->name, def->uuid);
4033

4034
 cleanup:
4035 4036
    virNetworkObjEndAPI(&obj);
    return net;
4037 4038 4039
}


4040 4041
static int
testConnectNumOfNetworks(virConnectPtr conn)
4042
{
4043
    testDriverPtr privconn = conn->privateData;
4044
    int numActive;
4045

4046 4047
    numActive = virNetworkObjListNumOfNetworks(privconn->networks,
                                               true, NULL, conn);
4048
    return numActive;
4049 4050
}

4051 4052 4053 4054

static int
testConnectListNetworks(virConnectPtr conn,
                        char **const names,
4055
                        int maxnames)
4056
{
4057
    testDriverPtr privconn = conn->privateData;
4058
    int n;
4059

4060
    n = virNetworkObjListGetNames(privconn->networks,
4061
                                  true, names, maxnames, NULL, conn);
4062
    return n;
4063 4064
}

4065 4066 4067

static int
testConnectNumOfDefinedNetworks(virConnectPtr conn)
4068
{
4069
    testDriverPtr privconn = conn->privateData;
4070
    int numInactive;
4071

4072 4073
    numInactive = virNetworkObjListNumOfNetworks(privconn->networks,
                                                 false, NULL, conn);
4074
    return numInactive;
4075 4076
}

4077 4078 4079 4080

static int
testConnectListDefinedNetworks(virConnectPtr conn,
                               char **const names,
4081
                               int maxnames)
4082
{
4083
    testDriverPtr privconn = conn->privateData;
4084
    int n;
4085

4086
    n = virNetworkObjListGetNames(privconn->networks,
4087
                                  false, names, maxnames, NULL, conn);
4088
    return n;
4089 4090
}

4091

4092
static int
4093
testConnectListAllNetworks(virConnectPtr conn,
4094 4095 4096
                           virNetworkPtr **nets,
                           unsigned int flags)
{
4097
    testDriverPtr privconn = conn->privateData;
4098 4099 4100

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

4101
    return virNetworkObjListExport(conn, privconn->networks, nets, NULL, flags);
4102
}
4103

4104 4105 4106

static int
testNetworkIsActive(virNetworkPtr net)
4107
{
4108
    testDriverPtr privconn = net->conn->privateData;
4109 4110 4111
    virNetworkObjPtr obj;
    int ret = -1;

4112
    if (!(obj = testNetworkObjFindByUUID(privconn, net->uuid)))
4113
        goto cleanup;
4114

4115 4116
    ret = virNetworkObjIsActive(obj);

4117
 cleanup:
4118
    virNetworkObjEndAPI(&obj);
4119 4120 4121
    return ret;
}

4122 4123 4124

static int
testNetworkIsPersistent(virNetworkPtr net)
4125
{
4126
    testDriverPtr privconn = net->conn->privateData;
4127 4128 4129
    virNetworkObjPtr obj;
    int ret = -1;

4130
    if (!(obj = testNetworkObjFindByUUID(privconn, net->uuid)))
4131
        goto cleanup;
4132

4133
    ret = virNetworkObjIsPersistent(obj);
4134

4135
 cleanup:
4136
    virNetworkObjEndAPI(&obj);
4137 4138 4139 4140
    return ret;
}


4141 4142
static virNetworkPtr
testNetworkCreateXML(virConnectPtr conn, const char *xml)
4143
{
4144
    testDriverPtr privconn = conn->privateData;
4145
    virNetworkDefPtr newDef;
4146
    virNetworkObjPtr obj = NULL;
4147
    virNetworkDefPtr def;
4148
    virNetworkPtr net = NULL;
4149
    virObjectEventPtr event = NULL;
4150

4151
    if ((newDef = virNetworkDefParseString(xml)) == NULL)
4152
        goto cleanup;
4153

4154
    if (!(obj = virNetworkObjAssignDef(privconn->networks, newDef,
4155 4156
                                       VIR_NETWORK_OBJ_LIST_ADD_LIVE |
                                       VIR_NETWORK_OBJ_LIST_ADD_CHECK_LIVE)))
4157
        goto cleanup;
4158 4159
    newDef = NULL;
    def = virNetworkObjGetDef(obj);
4160
    virNetworkObjSetActive(obj, true);
4161

4162
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
4163 4164
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
4165

4166
    net = virGetNetwork(conn, def->name, def->uuid);
4167

4168
 cleanup:
4169
    virNetworkDefFree(newDef);
4170
    virObjectEventStateQueue(privconn->eventState, event);
4171 4172
    virNetworkObjEndAPI(&obj);
    return net;
4173 4174
}

4175 4176 4177 4178

static virNetworkPtr
testNetworkDefineXML(virConnectPtr conn,
                     const char *xml)
4179
{
4180
    testDriverPtr privconn = conn->privateData;
4181
    virNetworkDefPtr newDef;
4182
    virNetworkObjPtr obj = NULL;
4183
    virNetworkDefPtr def;
4184
    virNetworkPtr net = NULL;
4185
    virObjectEventPtr event = NULL;
4186

4187
    if ((newDef = virNetworkDefParseString(xml)) == NULL)
4188
        goto cleanup;
4189

4190
    if (!(obj = virNetworkObjAssignDef(privconn->networks, newDef, 0)))
4191
        goto cleanup;
4192 4193
    newDef = NULL;
    def = virNetworkObjGetDef(obj);
4194

4195
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
4196 4197
                                        VIR_NETWORK_EVENT_DEFINED,
                                        0);
4198

4199
    net = virGetNetwork(conn, def->name, def->uuid);
4200

4201
 cleanup:
4202
    virNetworkDefFree(newDef);
4203
    virObjectEventStateQueue(privconn->eventState, event);
4204 4205
    virNetworkObjEndAPI(&obj);
    return net;
4206 4207
}

4208 4209

static int
4210
testNetworkUndefine(virNetworkPtr net)
4211
{
4212 4213
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
4214
    int ret = -1;
4215
    virObjectEventPtr event = NULL;
4216

4217
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
4218
        goto cleanup;
4219

4220
    if (virNetworkObjIsActive(obj)) {
4221
        virReportError(VIR_ERR_OPERATION_INVALID,
4222
                       _("Network '%s' is still running"), net->name);
4223
        goto cleanup;
4224 4225
    }

4226
    event = virNetworkEventLifecycleNew(net->name, net->uuid,
4227 4228
                                        VIR_NETWORK_EVENT_UNDEFINED,
                                        0);
4229

4230
    virNetworkObjRemoveInactive(privconn->networks, obj);
4231
    ret = 0;
4232

4233
 cleanup:
4234
    virObjectEventStateQueue(privconn->eventState, event);
4235
    virNetworkObjEndAPI(&obj);
4236
    return ret;
4237 4238
}

4239

4240 4241 4242 4243 4244 4245 4246 4247
static int
testNetworkUpdate(virNetworkPtr net,
                  unsigned int command,
                  unsigned int section,
                  int parentIndex,
                  const char *xml,
                  unsigned int flags)
{
4248
    testDriverPtr privconn = net->conn->privateData;
4249
    virNetworkObjPtr obj = NULL;
4250 4251 4252 4253 4254 4255
    int isActive, ret = -1;

    virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
                  VIR_NETWORK_UPDATE_AFFECT_CONFIG,
                  -1);

4256
    if (!(obj = testNetworkObjFindByUUID(privconn, net->uuid)))
4257 4258 4259 4260 4261
        goto cleanup;

    /* VIR_NETWORK_UPDATE_AFFECT_CURRENT means "change LIVE if network
     * is active, else change CONFIG
    */
4262
    isActive = virNetworkObjIsActive(obj);
4263 4264 4265 4266 4267 4268 4269 4270 4271 4272
    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 */
4273
    if (virNetworkObjUpdate(obj, command, section, parentIndex, xml, flags) < 0)
4274 4275 4276
       goto cleanup;

    ret = 0;
4277
 cleanup:
4278
    virNetworkObjEndAPI(&obj);
4279 4280 4281
    return ret;
}

4282 4283

static int
4284
testNetworkCreate(virNetworkPtr net)
4285
{
4286 4287
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
4288
    virNetworkDefPtr def;
4289
    int ret = -1;
4290
    virObjectEventPtr event = NULL;
4291

4292
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
4293
        goto cleanup;
4294
    def = virNetworkObjGetDef(obj);
4295

4296
    if (virNetworkObjIsActive(obj)) {
4297
        virReportError(VIR_ERR_OPERATION_INVALID,
4298
                       _("Network '%s' is already running"), net->name);
4299
        goto cleanup;
4300 4301
    }

4302
    virNetworkObjSetActive(obj, true);
4303
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
4304 4305
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
4306
    ret = 0;
4307

4308
 cleanup:
4309
    virObjectEventStateQueue(privconn->eventState, event);
4310
    virNetworkObjEndAPI(&obj);
4311
    return ret;
4312 4313
}

4314 4315

static int
4316
testNetworkDestroy(virNetworkPtr net)
4317
{
4318 4319
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
4320
    virNetworkDefPtr def;
4321
    int ret = -1;
4322
    virObjectEventPtr event = NULL;
4323

4324
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
4325
        goto cleanup;
4326
    def = virNetworkObjGetDef(obj);
4327

4328
    virNetworkObjSetActive(obj, false);
4329
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
4330 4331
                                        VIR_NETWORK_EVENT_STOPPED,
                                        0);
4332
    if (!virNetworkObjIsPersistent(obj))
4333
        virNetworkObjRemoveInactive(privconn->networks, obj);
4334

4335 4336
    ret = 0;

4337
 cleanup:
4338
    virObjectEventStateQueue(privconn->eventState, event);
4339
    virNetworkObjEndAPI(&obj);
4340
    return ret;
4341 4342
}

4343 4344

static char *
4345
testNetworkGetXMLDesc(virNetworkPtr net,
4346
                      unsigned int flags)
4347
{
4348 4349
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
4350
    char *ret = NULL;
4351

E
Eric Blake 已提交
4352 4353
    virCheckFlags(0, NULL);

4354
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
4355
        goto cleanup;
4356

4357
    ret = virNetworkDefFormat(virNetworkObjGetDef(obj), flags);
4358

4359
 cleanup:
4360
    virNetworkObjEndAPI(&obj);
4361
    return ret;
4362 4363
}

4364 4365

static char *
4366
testNetworkGetBridgeName(virNetworkPtr net)
4367
{
4368
    testDriverPtr privconn = net->conn->privateData;
4369
    char *bridge = NULL;
4370
    virNetworkObjPtr obj;
4371
    virNetworkDefPtr def;
4372

4373
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
4374
        goto cleanup;
4375
    def = virNetworkObjGetDef(obj);
4376

4377
    if (!(def->bridge)) {
4378 4379
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("network '%s' does not have a bridge name."),
4380
                       def->name);
4381 4382 4383
        goto cleanup;
    }

4384
    ignore_value(VIR_STRDUP(bridge, def->bridge));
4385

4386
 cleanup:
4387
    virNetworkObjEndAPI(&obj);
4388 4389 4390
    return bridge;
}

4391 4392

static int
4393
testNetworkGetAutostart(virNetworkPtr net,
4394
                        int *autostart)
4395
{
4396 4397
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
4398
    int ret = -1;
4399

4400
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
4401
        goto cleanup;
4402

4403
    *autostart = virNetworkObjIsAutostart(obj) ? 1 : 0;
4404 4405
    ret = 0;

4406
 cleanup:
4407
    virNetworkObjEndAPI(&obj);
4408
    return ret;
4409 4410
}

4411 4412

static int
4413
testNetworkSetAutostart(virNetworkPtr net,
4414
                        int autostart)
4415
{
4416 4417
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
4418
    bool new_autostart = (autostart != 0);
4419
    int ret = -1;
4420

4421
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
4422
        goto cleanup;
4423

4424 4425
    virNetworkObjSetAutostart(obj, new_autostart);

4426 4427
    ret = 0;

4428
 cleanup:
4429
    virNetworkObjEndAPI(&obj);
4430
    return ret;
4431
}
4432

C
Cole Robinson 已提交
4433

L
Laine Stump 已提交
4434 4435 4436 4437 4438
/*
 * Physical host interface routines
 */


4439 4440 4441 4442
static virInterfaceObjPtr
testInterfaceObjFindByName(testDriverPtr privconn,
                           const char *name)
{
4443
    virInterfaceObjPtr obj;
4444

4445
    virObjectLock(privconn);
4446
    obj = virInterfaceObjListFindByName(privconn->ifaces, name);
4447
    virObjectUnlock(privconn);
4448

4449
    if (!obj)
4450 4451 4452 4453
        virReportError(VIR_ERR_NO_INTERFACE,
                       _("no interface with matching name '%s'"),
                       name);

4454
    return obj;
4455 4456 4457
}


4458 4459
static int
testConnectNumOfInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
4460
{
4461
    testDriverPtr privconn = conn->privateData;
4462
    int ninterfaces;
L
Laine Stump 已提交
4463

4464
    virObjectLock(privconn);
4465
    ninterfaces = virInterfaceObjListNumOfInterfaces(privconn->ifaces, true);
4466
    virObjectUnlock(privconn);
4467
    return ninterfaces;
L
Laine Stump 已提交
4468 4469
}

4470 4471 4472 4473 4474

static int
testConnectListInterfaces(virConnectPtr conn,
                          char **const names,
                          int maxnames)
L
Laine Stump 已提交
4475
{
4476
    testDriverPtr privconn = conn->privateData;
4477
    int nnames;
L
Laine Stump 已提交
4478

4479
    virObjectLock(privconn);
4480 4481
    nnames = virInterfaceObjListGetNames(privconn->ifaces, true,
                                         names, maxnames);
4482
    virObjectUnlock(privconn);
L
Laine Stump 已提交
4483

4484
    return nnames;
L
Laine Stump 已提交
4485 4486
}

4487 4488 4489

static int
testConnectNumOfDefinedInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
4490
{
4491
    testDriverPtr privconn = conn->privateData;
4492
    int ninterfaces;
L
Laine Stump 已提交
4493

4494
    virObjectLock(privconn);
4495
    ninterfaces = virInterfaceObjListNumOfInterfaces(privconn->ifaces, false);
4496
    virObjectUnlock(privconn);
4497
    return ninterfaces;
L
Laine Stump 已提交
4498 4499
}

4500 4501 4502 4503 4504

static int
testConnectListDefinedInterfaces(virConnectPtr conn,
                                 char **const names,
                                 int maxnames)
L
Laine Stump 已提交
4505
{
4506
    testDriverPtr privconn = conn->privateData;
4507
    int nnames;
L
Laine Stump 已提交
4508

4509
    virObjectLock(privconn);
4510 4511
    nnames = virInterfaceObjListGetNames(privconn->ifaces, false,
                                         names, maxnames);
4512
    virObjectUnlock(privconn);
L
Laine Stump 已提交
4513

4514
    return nnames;
L
Laine Stump 已提交
4515 4516
}

4517

4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531
static int
testConnectListAllInterfaces(virConnectPtr conn,
                             virInterfacePtr **ifaces,
                             unsigned int flags)
{
    testDriverPtr privconn = conn->privateData;

    virCheckFlags(VIR_CONNECT_LIST_INTERFACES_FILTERS_ACTIVE, -1);

    return virInterfaceObjListExport(conn, privconn->ifaces, ifaces,
                                     NULL, flags);
}


4532 4533 4534
static virInterfacePtr
testInterfaceLookupByName(virConnectPtr conn,
                          const char *name)
L
Laine Stump 已提交
4535
{
4536
    testDriverPtr privconn = conn->privateData;
4537
    virInterfaceObjPtr obj;
4538
    virInterfaceDefPtr def;
L
Laine Stump 已提交
4539 4540
    virInterfacePtr ret = NULL;

4541
    if (!(obj = testInterfaceObjFindByName(privconn, name)))
4542
        return NULL;
4543
    def = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
4544

4545
    ret = virGetInterface(conn, def->name, def->mac);
L
Laine Stump 已提交
4546

4547
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
4548 4549 4550
    return ret;
}

4551 4552 4553 4554

static virInterfacePtr
testInterfaceLookupByMACString(virConnectPtr conn,
                               const char *mac)
L
Laine Stump 已提交
4555
{
4556
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
4557
    int ifacect;
4558
    char *ifacenames[] = { NULL, NULL };
L
Laine Stump 已提交
4559 4560
    virInterfacePtr ret = NULL;

4561
    virObjectLock(privconn);
4562 4563
    ifacect = virInterfaceObjListFindByMACString(privconn->ifaces, mac,
                                                 ifacenames, 2);
4564
    virObjectUnlock(privconn);
L
Laine Stump 已提交
4565 4566

    if (ifacect == 0) {
4567 4568
        virReportError(VIR_ERR_NO_INTERFACE,
                       _("no interface with matching mac '%s'"), mac);
L
Laine Stump 已提交
4569 4570 4571 4572
        goto cleanup;
    }

    if (ifacect > 1) {
4573
        virReportError(VIR_ERR_MULTIPLE_INTERFACES, NULL);
L
Laine Stump 已提交
4574 4575 4576
        goto cleanup;
    }

4577
    ret = virGetInterface(conn, ifacenames[0], mac);
L
Laine Stump 已提交
4578

4579
 cleanup:
4580 4581
    VIR_FREE(ifacenames[0]);
    VIR_FREE(ifacenames[1]);
L
Laine Stump 已提交
4582 4583 4584
    return ret;
}

4585 4586 4587

static int
testInterfaceIsActive(virInterfacePtr iface)
4588
{
4589
    testDriverPtr privconn = iface->conn->privateData;
4590 4591 4592
    virInterfaceObjPtr obj;
    int ret = -1;

4593
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
4594
        return -1;
4595

4596 4597
    ret = virInterfaceObjIsActive(obj);

4598
    virInterfaceObjEndAPI(&obj);
4599 4600 4601
    return ret;
}

4602 4603 4604 4605

static int
testInterfaceChangeBegin(virConnectPtr conn,
                         unsigned int flags)
4606
{
4607
    testDriverPtr privconn = conn->privateData;
4608 4609
    int ret = -1;

E
Eric Blake 已提交
4610 4611
    virCheckFlags(0, -1);

4612
    virObjectLock(privconn);
4613
    if (privconn->transaction_running) {
4614
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
4615
                       _("there is another transaction running."));
4616 4617 4618 4619 4620
        goto cleanup;
    }

    privconn->transaction_running = true;

4621
    if (!(privconn->backupIfaces = virInterfaceObjListClone(privconn->ifaces)))
4622 4623 4624
        goto cleanup;

    ret = 0;
4625
 cleanup:
4626
    virObjectUnlock(privconn);
4627 4628 4629
    return ret;
}

4630 4631 4632 4633

static int
testInterfaceChangeCommit(virConnectPtr conn,
                          unsigned int flags)
4634
{
4635
    testDriverPtr privconn = conn->privateData;
4636 4637
    int ret = -1;

E
Eric Blake 已提交
4638 4639
    virCheckFlags(0, -1);

4640
    virObjectLock(privconn);
4641 4642

    if (!privconn->transaction_running) {
4643
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
4644 4645
                       _("no transaction running, "
                         "nothing to be committed."));
4646 4647 4648
        goto cleanup;
    }

4649
    virObjectUnref(privconn->backupIfaces);
4650 4651 4652 4653
    privconn->transaction_running = false;

    ret = 0;

4654
 cleanup:
4655
    virObjectUnlock(privconn);
4656 4657 4658 4659

    return ret;
}

4660 4661 4662 4663

static int
testInterfaceChangeRollback(virConnectPtr conn,
                            unsigned int flags)
4664
{
4665
    testDriverPtr privconn = conn->privateData;
4666 4667
    int ret = -1;

E
Eric Blake 已提交
4668 4669
    virCheckFlags(0, -1);

4670
    virObjectLock(privconn);
4671 4672

    if (!privconn->transaction_running) {
4673
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
4674 4675
                       _("no transaction running, "
                         "nothing to rollback."));
4676 4677 4678
        goto cleanup;
    }

4679
    virObjectUnref(privconn->ifaces);
4680 4681
    privconn->ifaces = privconn->backupIfaces;
    privconn->backupIfaces = NULL;
4682 4683 4684 4685 4686

    privconn->transaction_running = false;

    ret = 0;

4687
 cleanup:
4688
    virObjectUnlock(privconn);
4689 4690
    return ret;
}
4691

4692 4693 4694 4695

static char *
testInterfaceGetXMLDesc(virInterfacePtr iface,
                        unsigned int flags)
L
Laine Stump 已提交
4696
{
4697
    testDriverPtr privconn = iface->conn->privateData;
4698
    virInterfaceObjPtr obj;
4699
    virInterfaceDefPtr def;
L
Laine Stump 已提交
4700 4701
    char *ret = NULL;

E
Eric Blake 已提交
4702 4703
    virCheckFlags(0, NULL);

4704
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
4705
        return NULL;
4706
    def = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
4707

4708
    ret = virInterfaceDefFormat(def);
L
Laine Stump 已提交
4709

4710
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
4711 4712 4713 4714
    return ret;
}


4715 4716 4717 4718
static virInterfacePtr
testInterfaceDefineXML(virConnectPtr conn,
                       const char *xmlStr,
                       unsigned int flags)
L
Laine Stump 已提交
4719
{
4720
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
4721
    virInterfaceDefPtr def;
4722
    virInterfaceObjPtr obj = NULL;
4723
    virInterfaceDefPtr objdef;
L
Laine Stump 已提交
4724 4725
    virInterfacePtr ret = NULL;

E
Eric Blake 已提交
4726 4727
    virCheckFlags(0, NULL);

4728
    virObjectLock(privconn);
4729
    if ((def = virInterfaceDefParseString(xmlStr)) == NULL)
L
Laine Stump 已提交
4730 4731
        goto cleanup;

4732
    if ((obj = virInterfaceObjListAssignDef(privconn->ifaces, def)) == NULL)
L
Laine Stump 已提交
4733 4734
        goto cleanup;
    def = NULL;
4735
    objdef = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
4736

4737
    ret = virGetInterface(conn, objdef->name, objdef->mac);
L
Laine Stump 已提交
4738

4739
 cleanup:
L
Laine Stump 已提交
4740
    virInterfaceDefFree(def);
4741
    virInterfaceObjEndAPI(&obj);
4742
    virObjectUnlock(privconn);
L
Laine Stump 已提交
4743 4744 4745
    return ret;
}

4746 4747 4748

static int
testInterfaceUndefine(virInterfacePtr iface)
L
Laine Stump 已提交
4749
{
4750
    testDriverPtr privconn = iface->conn->privateData;
4751
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
4752

4753
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
4754
        return -1;
L
Laine Stump 已提交
4755

4756
    virInterfaceObjListRemove(privconn->ifaces, obj);
4757
    virObjectUnref(obj);
L
Laine Stump 已提交
4758

4759
    return 0;
L
Laine Stump 已提交
4760 4761
}

4762 4763 4764 4765

static int
testInterfaceCreate(virInterfacePtr iface,
                    unsigned int flags)
L
Laine Stump 已提交
4766
{
4767
    testDriverPtr privconn = iface->conn->privateData;
4768
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
4769 4770
    int ret = -1;

E
Eric Blake 已提交
4771 4772
    virCheckFlags(0, -1);

4773
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
4774
        return -1;
L
Laine Stump 已提交
4775

4776
    if (virInterfaceObjIsActive(obj)) {
4777
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
4778 4779 4780
        goto cleanup;
    }

4781
    virInterfaceObjSetActive(obj, true);
L
Laine Stump 已提交
4782 4783
    ret = 0;

4784
 cleanup:
4785
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
4786 4787 4788
    return ret;
}

4789 4790 4791 4792

static int
testInterfaceDestroy(virInterfacePtr iface,
                     unsigned int flags)
L
Laine Stump 已提交
4793
{
4794
    testDriverPtr privconn = iface->conn->privateData;
4795
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
4796 4797
    int ret = -1;

E
Eric Blake 已提交
4798 4799
    virCheckFlags(0, -1);

4800
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
4801
        return -1;
L
Laine Stump 已提交
4802

4803
    if (!virInterfaceObjIsActive(obj)) {
4804
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
4805 4806 4807
        goto cleanup;
    }

4808
    virInterfaceObjSetActive(obj, false);
L
Laine Stump 已提交
4809 4810
    ret = 0;

4811
 cleanup:
4812
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
4813 4814 4815 4816 4817
    return ret;
}



C
Cole Robinson 已提交
4818 4819 4820 4821
/*
 * Storage Driver routines
 */

4822
static int
4823
testStoragePoolObjSetDefaults(virStoragePoolObjPtr obj)
4824
{
4825
    char *configFile;
4826
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4827

4828 4829 4830
    def->capacity = defaultPoolCap;
    def->allocation = defaultPoolAlloc;
    def->available = defaultPoolCap - defaultPoolAlloc;
C
Cole Robinson 已提交
4831

4832 4833 4834 4835 4836
    if (VIR_STRDUP(configFile, "") < 0)
        return -1;

    virStoragePoolObjSetConfigFile(obj, configFile);
    return 0;
C
Cole Robinson 已提交
4837 4838
}

4839

4840 4841 4842 4843
static virStoragePoolObjPtr
testStoragePoolObjFindByName(testDriverPtr privconn,
                             const char *name)
{
4844
    virStoragePoolObjPtr obj;
4845

4846
    virObjectLock(privconn);
4847
    obj = virStoragePoolObjFindByName(privconn->pools, name);
4848
    virObjectUnlock(privconn);
4849

4850
    if (!obj)
4851 4852 4853 4854
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       name);

4855
    return obj;
4856 4857 4858
}


4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870
static virStoragePoolObjPtr
testStoragePoolObjFindActiveByName(testDriverPtr privconn,
                                   const char *name)
{
    virStoragePoolObjPtr obj;

    if (!(obj = testStoragePoolObjFindByName(privconn, name)))
        return NULL;

    if (!virStoragePoolObjIsActive(obj)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), name);
4871
        virStoragePoolObjEndAPI(&obj);
4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890
        return NULL;
    }

    return obj;
}


static virStoragePoolObjPtr
testStoragePoolObjFindInactiveByName(testDriverPtr privconn,
                                     const char *name)
{
    virStoragePoolObjPtr obj;

    if (!(obj = testStoragePoolObjFindByName(privconn, name)))
        return NULL;

    if (virStoragePoolObjIsActive(obj)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is active"), name);
4891
        virStoragePoolObjEndAPI(&obj);
4892 4893 4894 4895 4896 4897 4898
        return NULL;
    }

    return obj;
}


4899 4900 4901 4902
static virStoragePoolObjPtr
testStoragePoolObjFindByUUID(testDriverPtr privconn,
                             const unsigned char *uuid)
{
4903
    virStoragePoolObjPtr obj;
4904 4905
    char uuidstr[VIR_UUID_STRING_BUFLEN];

4906
    virObjectLock(privconn);
4907
    obj = virStoragePoolObjFindByUUID(privconn->pools, uuid);
4908
    virObjectUnlock(privconn);
4909

4910
    if (!obj) {
4911 4912 4913 4914 4915 4916
        virUUIDFormat(uuid, uuidstr);
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching uuid '%s'"),
                       uuidstr);
    }

4917
    return obj;
4918 4919 4920
}


C
Cole Robinson 已提交
4921 4922
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
4923 4924
                            const unsigned char *uuid)
{
4925
    testDriverPtr privconn = conn->privateData;
4926
    virStoragePoolObjPtr obj;
4927
    virStoragePoolDefPtr def;
4928
    virStoragePoolPtr pool = NULL;
C
Cole Robinson 已提交
4929

4930
    if (!(obj = testStoragePoolObjFindByUUID(privconn, uuid)))
4931
        return NULL;
4932
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4933

4934
    pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
4935

4936
    virStoragePoolObjEndAPI(&obj);
4937
    return pool;
C
Cole Robinson 已提交
4938 4939
}

4940

C
Cole Robinson 已提交
4941 4942
static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
4943 4944
                            const char *name)
{
4945
    testDriverPtr privconn = conn->privateData;
4946
    virStoragePoolObjPtr obj;
4947
    virStoragePoolDefPtr def;
4948
    virStoragePoolPtr pool = NULL;
C
Cole Robinson 已提交
4949

4950
    if (!(obj = testStoragePoolObjFindByName(privconn, name)))
4951
        return NULL;
4952
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
4953

4954
    pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
4955

4956
    virStoragePoolObjEndAPI(&obj);
4957
    return pool;
C
Cole Robinson 已提交
4958 4959
}

4960

C
Cole Robinson 已提交
4961
static virStoragePoolPtr
4962 4963
testStoragePoolLookupByVolume(virStorageVolPtr vol)
{
C
Cole Robinson 已提交
4964 4965 4966
    return testStoragePoolLookupByName(vol->conn, vol->pool);
}

4967

C
Cole Robinson 已提交
4968
static int
4969 4970
testConnectNumOfStoragePools(virConnectPtr conn)
{
4971
    testDriverPtr privconn = conn->privateData;
4972
    int numActive = 0;
C
Cole Robinson 已提交
4973

4974
    virObjectLock(privconn);
4975
    numActive = virStoragePoolObjNumOfStoragePools(privconn->pools, conn,
4976
                                                   true, NULL);
4977
    virObjectUnlock(privconn);
C
Cole Robinson 已提交
4978 4979 4980 4981

    return numActive;
}

4982

C
Cole Robinson 已提交
4983
static int
4984 4985
testConnectListStoragePools(virConnectPtr conn,
                            char **const names,
4986
                            int maxnames)
4987
{
4988
    testDriverPtr privconn = conn->privateData;
4989
    int n = 0;
C
Cole Robinson 已提交
4990

4991
    virObjectLock(privconn);
4992
    n = virStoragePoolObjGetNames(privconn->pools, conn, true, NULL,
4993
                                  names, maxnames);
4994
    virObjectUnlock(privconn);
C
Cole Robinson 已提交
4995 4996 4997 4998

    return n;
}

4999

C
Cole Robinson 已提交
5000
static int
5001 5002
testConnectNumOfDefinedStoragePools(virConnectPtr conn)
{
5003
    testDriverPtr privconn = conn->privateData;
5004
    int numInactive = 0;
C
Cole Robinson 已提交
5005

5006
    virObjectLock(privconn);
5007
    numInactive = virStoragePoolObjNumOfStoragePools(privconn->pools, conn,
5008
                                                     false, NULL);
5009
    virObjectUnlock(privconn);
C
Cole Robinson 已提交
5010 5011 5012 5013

    return numInactive;
}

5014

C
Cole Robinson 已提交
5015
static int
5016 5017
testConnectListDefinedStoragePools(virConnectPtr conn,
                                   char **const names,
5018
                                   int maxnames)
5019
{
5020
    testDriverPtr privconn = conn->privateData;
5021
    int n = 0;
C
Cole Robinson 已提交
5022

5023
    virObjectLock(privconn);
5024
    n = virStoragePoolObjGetNames(privconn->pools, conn, false, NULL,
5025
                                  names, maxnames);
5026
    virObjectUnlock(privconn);
C
Cole Robinson 已提交
5027 5028 5029 5030

    return n;
}

5031

5032
static int
5033 5034 5035
testConnectListAllStoragePools(virConnectPtr conn,
                               virStoragePoolPtr **pools,
                               unsigned int flags)
5036
{
5037
    testDriverPtr privconn = conn->privateData;
5038 5039 5040 5041
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

5042
    virObjectLock(privconn);
5043
    ret = virStoragePoolObjListExport(conn, privconn->pools, pools,
5044
                                      NULL, flags);
5045
    virObjectUnlock(privconn);
5046 5047 5048

    return ret;
}
C
Cole Robinson 已提交
5049

5050 5051 5052

static int
testStoragePoolIsActive(virStoragePoolPtr pool)
5053
{
5054
    testDriverPtr privconn = pool->conn->privateData;
5055 5056 5057
    virStoragePoolObjPtr obj;
    int ret = -1;

5058
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
5059
        goto cleanup;
5060

5061 5062
    ret = virStoragePoolObjIsActive(obj);

5063
 cleanup:
5064
    if (obj)
5065
        virStoragePoolObjEndAPI(&obj);
5066 5067 5068
    return ret;
}

5069 5070 5071

static int
testStoragePoolIsPersistent(virStoragePoolPtr pool)
5072
{
5073
    testDriverPtr privconn = pool->conn->privateData;
5074 5075 5076
    virStoragePoolObjPtr obj;
    int ret = -1;

5077
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
5078
        return -1;
5079

5080
    ret = virStoragePoolObjGetConfigFile(obj) ? 1 : 0;
5081

5082
    virStoragePoolObjEndAPI(&obj);
5083 5084 5085 5086
    return ret;
}


C
Cole Robinson 已提交
5087
static int
5088 5089
testStoragePoolCreate(virStoragePoolPtr pool,
                      unsigned int flags)
E
Eric Blake 已提交
5090
{
5091
    testDriverPtr privconn = pool->conn->privateData;
5092
    virStoragePoolObjPtr obj;
5093
    virObjectEventPtr event = NULL;
5094

E
Eric Blake 已提交
5095 5096
    virCheckFlags(0, -1);

5097 5098
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
5099

5100
    virStoragePoolObjSetActive(obj, true);
5101 5102 5103 5104

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

5106
    virObjectEventStateQueue(privconn->eventState, event);
5107
    virStoragePoolObjEndAPI(&obj);
5108
    return 0;
C
Cole Robinson 已提交
5109 5110
}

5111

C
Cole Robinson 已提交
5112
static char *
5113 5114 5115 5116
testConnectFindStoragePoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  const char *type,
                                  const char *srcSpec,
                                  unsigned int flags)
C
Cole Robinson 已提交
5117
{
5118 5119
    int pool_type;
    char *ret = NULL;
5120
    VIR_AUTOPTR(virStoragePoolSource) source = NULL;
5121

E
Eric Blake 已提交
5122 5123
    virCheckFlags(0, NULL);

5124 5125
    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
5126 5127
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
5128
        return NULL;
5129 5130 5131
    }

    if (srcSpec) {
5132
        source = virStoragePoolDefParseSourceString(srcSpec, pool_type);
5133
        if (!source)
5134
            return NULL;
5135 5136 5137 5138 5139
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
5140
        ignore_value(VIR_STRDUP(ret, defaultPoolSourcesLogicalXML));
5141
        return ret;
5142 5143

    case VIR_STORAGE_POOL_NETFS:
5144
        if (!source || !source->hosts[0].name) {
5145 5146
            virReportError(VIR_ERR_INVALID_ARG,
                           "%s", _("hostname must be specified for netfs sources"));
5147
            return NULL;
5148 5149
        }

5150 5151
        ignore_value(virAsprintf(&ret, defaultPoolSourcesNetFSXML,
                                 source->hosts[0].name));
5152
        return ret;
5153 5154

    default:
5155 5156
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source discovery"), type);
5157 5158
    }

5159
    return NULL;
C
Cole Robinson 已提交
5160 5161 5162
}


5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184
static virNodeDeviceObjPtr
testNodeDeviceMockCreateVport(testDriverPtr driver,
                              const char *wwnn,
                              const char *wwpn);
static int
testCreateVport(testDriverPtr driver,
                const char *wwnn,
                const char *wwpn)
{
    virNodeDeviceObjPtr obj = NULL;
    /* The storage_backend_scsi createVport() will use the input adapter
     * fields parent name, parent_wwnn/parent_wwpn, or parent_fabric_wwn
     * in order to determine whether the provided parent can be used to
     * create a vHBA or will find "an available vport capable" to create
     * a vHBA. In order to do this, it uses the virVHBA* API's which traverse
     * the sysfs looking at various fields (rather than going via nodedev).
     *
     * Since the test environ doesn't have the sysfs for the storage pool
     * test, at least for now use the node device test infrastructure to
     * create the vHBA. In the long run the result is the same. */
    if (!(obj = testNodeDeviceMockCreateVport(driver, wwnn, wwpn)))
        return -1;
5185
    virNodeDeviceObjEndAPI(&obj);
5186 5187 5188 5189 5190

    return 0;
}


C
Cole Robinson 已提交
5191
static virStoragePoolPtr
5192 5193 5194
testStoragePoolCreateXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
5195
{
5196
    testDriverPtr privconn = conn->privateData;
5197
    virStoragePoolObjPtr obj = NULL;
5198
    virStoragePoolDefPtr def;
5199
    virStoragePoolPtr pool = NULL;
5200
    virObjectEventPtr event = NULL;
5201
    VIR_AUTOPTR(virStoragePoolDef) newDef = NULL;
C
Cole Robinson 已提交
5202

E
Eric Blake 已提交
5203 5204
    virCheckFlags(0, NULL);

5205
    virObjectLock(privconn);
5206
    if (!(newDef = virStoragePoolDefParseString(xml)))
5207
        goto cleanup;
C
Cole Robinson 已提交
5208

5209
    if (!(obj = virStoragePoolObjAssignDef(privconn->pools, newDef, true)))
5210
        goto cleanup;
5211 5212
    newDef = NULL;
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
5213

5214
    if (def->source.adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
5215 5216 5217 5218 5219
        /* In the real code, we'd call virVHBAManageVport followed by
         * find_new_device, but we cannot do that here since we're not
         * mocking udev. The mock routine will copy an existing vHBA and
         * rename a few fields to mock that. */
        if (testCreateVport(privconn,
5220 5221
                            def->source.adapter.data.fchost.wwnn,
                            def->source.adapter.data.fchost.wwpn) < 0) {
5222
            virStoragePoolObjRemove(privconn->pools, obj);
5223
            virObjectUnref(obj);
5224
            obj = NULL;
5225 5226 5227 5228
            goto cleanup;
        }
    }

5229
    if (testStoragePoolObjSetDefaults(obj) == -1) {
5230
        virStoragePoolObjRemove(privconn->pools, obj);
5231
        virObjectUnref(obj);
5232
        obj = NULL;
5233
        goto cleanup;
C
Cole Robinson 已提交
5234
    }
5235 5236 5237 5238

    /* *SetDefaults fills this in for the persistent pools, but this
     * would be a transient pool so remove it; otherwise, the Destroy
     * code will not Remove the pool */
5239
    virStoragePoolObjSetConfigFile(obj, NULL);
5240

5241
    virStoragePoolObjSetActive(obj, true);
C
Cole Robinson 已提交
5242

5243
    event = virStoragePoolEventLifecycleNew(def->name, def->uuid,
5244 5245 5246
                                            VIR_STORAGE_POOL_EVENT_STARTED,
                                            0);

5247
    pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
5248

5249
 cleanup:
5250
    virObjectEventStateQueue(privconn->eventState, event);
5251
    virStoragePoolObjEndAPI(&obj);
5252
    virObjectUnlock(privconn);
5253
    return pool;
C
Cole Robinson 已提交
5254 5255
}

5256

C
Cole Robinson 已提交
5257
static virStoragePoolPtr
5258 5259 5260
testStoragePoolDefineXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
5261
{
5262
    testDriverPtr privconn = conn->privateData;
5263
    virStoragePoolObjPtr obj = NULL;
5264
    virStoragePoolDefPtr def;
5265
    virStoragePoolPtr pool = NULL;
5266
    virObjectEventPtr event = NULL;
5267
    VIR_AUTOPTR(virStoragePoolDef) newDef = NULL;
C
Cole Robinson 已提交
5268

E
Eric Blake 已提交
5269 5270
    virCheckFlags(0, NULL);

5271
    virObjectLock(privconn);
5272
    if (!(newDef = virStoragePoolDefParseString(xml)))
5273
        goto cleanup;
C
Cole Robinson 已提交
5274

5275 5276 5277
    newDef->capacity = defaultPoolCap;
    newDef->allocation = defaultPoolAlloc;
    newDef->available = defaultPoolCap - defaultPoolAlloc;
C
Cole Robinson 已提交
5278

5279
    if (!(obj = virStoragePoolObjAssignDef(privconn->pools, newDef, false)))
5280
        goto cleanup;
5281 5282
    newDef = NULL;
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
5283

5284
    event = virStoragePoolEventLifecycleNew(def->name, def->uuid,
5285 5286 5287
                                            VIR_STORAGE_POOL_EVENT_DEFINED,
                                            0);

5288
    if (testStoragePoolObjSetDefaults(obj) == -1) {
5289
        virStoragePoolObjRemove(privconn->pools, obj);
5290
        virObjectUnref(obj);
5291
        obj = NULL;
5292
        goto cleanup;
C
Cole Robinson 已提交
5293 5294
    }

5295
    pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
5296

5297
 cleanup:
5298
    virObjectEventStateQueue(privconn->eventState, event);
5299
    virStoragePoolObjEndAPI(&obj);
5300
    virObjectUnlock(privconn);
5301
    return pool;
C
Cole Robinson 已提交
5302 5303
}

5304

C
Cole Robinson 已提交
5305
static int
5306 5307
testStoragePoolUndefine(virStoragePoolPtr pool)
{
5308
    testDriverPtr privconn = pool->conn->privateData;
5309
    virStoragePoolObjPtr obj;
5310
    virObjectEventPtr event = NULL;
5311

5312 5313
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
5314

5315 5316 5317 5318
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_UNDEFINED,
                                            0);

5319
    virStoragePoolObjRemove(privconn->pools, obj);
5320
    virObjectUnref(obj);
C
Cole Robinson 已提交
5321

5322
    virObjectEventStateQueue(privconn->eventState, event);
5323
    return 0;
C
Cole Robinson 已提交
5324 5325
}

5326

C
Cole Robinson 已提交
5327
static int
5328
testStoragePoolBuild(virStoragePoolPtr pool,
E
Eric Blake 已提交
5329 5330
                     unsigned int flags)
{
5331
    testDriverPtr privconn = pool->conn->privateData;
5332
    virStoragePoolObjPtr obj;
5333
    virObjectEventPtr event = NULL;
5334

E
Eric Blake 已提交
5335 5336
    virCheckFlags(0, -1);

5337 5338
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
5339

5340 5341 5342 5343
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_CREATED,
                                            0);

5344
    virStoragePoolObjEndAPI(&obj);
5345

5346
    virObjectEventStateQueue(privconn->eventState, event);
5347
    return 0;
C
Cole Robinson 已提交
5348 5349 5350
}


5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365
static int
testDestroyVport(testDriverPtr privconn,
                 const char *wwnn ATTRIBUTE_UNUSED,
                 const char *wwpn ATTRIBUTE_UNUSED)
{
    virNodeDeviceObjPtr obj = NULL;
    virObjectEventPtr event = NULL;

    /* NB: Cannot use virVHBAGetHostByWWN (yet) like the storage_backend_scsi
     * deleteVport() helper since that traverses the file system looking for
     * the wwnn/wwpn. So our choice short term is to cheat and use the name
     * (scsi_host12) we know was created.
     *
     * Reaching across the boundaries of space and time into the
     * Node Device in order to remove */
5366 5367
    if (!(obj = virNodeDeviceObjListFindByName(privconn->devs,
                                               "scsi_host12"))) {
5368 5369
        virReportError(VIR_ERR_NO_NODE_DEVICE, "%s",
                       _("no node device with matching name 'scsi_host12'"));
5370
        return -1;
5371 5372 5373 5374 5375 5376
    }

    event = virNodeDeviceEventLifecycleNew("scsi_host12",
                                           VIR_NODE_DEVICE_EVENT_DELETED,
                                           0);

5377
    virNodeDeviceObjListRemove(privconn->devs, obj);
5378
    virObjectUnref(obj);
5379

5380
    virObjectEventStateQueue(privconn->eventState, event);
5381
    return 0;
5382 5383 5384
}


C
Cole Robinson 已提交
5385
static int
5386 5387
testStoragePoolDestroy(virStoragePoolPtr pool)
{
5388
    testDriverPtr privconn = pool->conn->privateData;
5389
    virStoragePoolObjPtr obj;
5390
    virStoragePoolDefPtr def;
5391
    int ret = -1;
5392
    virObjectEventPtr event = NULL;
5393

5394
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
5395
        return -1;
5396
    def = virStoragePoolObjGetDef(obj);
5397

5398
    virStoragePoolObjSetActive(obj, false);
5399

5400
    if (def->source.adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
5401
        if (testDestroyVport(privconn,
5402 5403
                             def->source.adapter.data.fchost.wwnn,
                             def->source.adapter.data.fchost.wwpn) < 0)
5404 5405 5406
            goto cleanup;
    }

5407 5408
    event = virStoragePoolEventLifecycleNew(def->name,
                                            def->uuid,
5409 5410
                                            VIR_STORAGE_POOL_EVENT_STOPPED,
                                            0);
C
Cole Robinson 已提交
5411

5412
    if (!(virStoragePoolObjGetConfigFile(obj))) {
5413
        virStoragePoolObjRemove(privconn->pools, obj);
5414
        virObjectUnref(obj);
5415
        obj = NULL;
5416
    }
5417
    ret = 0;
C
Cole Robinson 已提交
5418

5419
 cleanup:
5420
    virObjectEventStateQueue(privconn->eventState, event);
5421
    virStoragePoolObjEndAPI(&obj);
5422
    return ret;
C
Cole Robinson 已提交
5423 5424 5425 5426
}


static int
5427
testStoragePoolDelete(virStoragePoolPtr pool,
E
Eric Blake 已提交
5428 5429
                      unsigned int flags)
{
5430
    testDriverPtr privconn = pool->conn->privateData;
5431
    virStoragePoolObjPtr obj;
5432
    virObjectEventPtr event = NULL;
5433

E
Eric Blake 已提交
5434 5435
    virCheckFlags(0, -1);

5436 5437
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
5438

5439 5440 5441 5442
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_DELETED,
                                            0);

5443
    virObjectEventStateQueue(privconn->eventState, event);
5444

5445
    virStoragePoolObjEndAPI(&obj);
5446
    return 0;
C
Cole Robinson 已提交
5447 5448 5449 5450
}


static int
5451
testStoragePoolRefresh(virStoragePoolPtr pool,
E
Eric Blake 已提交
5452 5453
                       unsigned int flags)
{
5454
    testDriverPtr privconn = pool->conn->privateData;
5455
    virStoragePoolObjPtr obj;
5456
    virObjectEventPtr event = NULL;
5457

E
Eric Blake 已提交
5458 5459
    virCheckFlags(0, -1);

5460 5461
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return -1;
5462

5463
    event = virStoragePoolEventRefreshNew(pool->name, pool->uuid);
C
Cole Robinson 已提交
5464

5465
    virObjectEventStateQueue(privconn->eventState, event);
5466
    virStoragePoolObjEndAPI(&obj);
5467
    return 0;
C
Cole Robinson 已提交
5468 5469 5470 5471
}


static int
5472
testStoragePoolGetInfo(virStoragePoolPtr pool,
5473 5474
                       virStoragePoolInfoPtr info)
{
5475
    testDriverPtr privconn = pool->conn->privateData;
5476
    virStoragePoolObjPtr obj;
5477
    virStoragePoolDefPtr def;
5478

5479
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
5480
        return -1;
5481
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
5482 5483

    memset(info, 0, sizeof(virStoragePoolInfo));
5484
    if (virStoragePoolObjIsActive(obj))
C
Cole Robinson 已提交
5485 5486 5487
        info->state = VIR_STORAGE_POOL_RUNNING;
    else
        info->state = VIR_STORAGE_POOL_INACTIVE;
5488 5489 5490
    info->capacity = def->capacity;
    info->allocation = def->allocation;
    info->available = def->available;
C
Cole Robinson 已提交
5491

5492
    virStoragePoolObjEndAPI(&obj);
5493
    return 0;
C
Cole Robinson 已提交
5494 5495
}

5496

C
Cole Robinson 已提交
5497
static char *
5498
testStoragePoolGetXMLDesc(virStoragePoolPtr pool,
E
Eric Blake 已提交
5499 5500
                          unsigned int flags)
{
5501
    testDriverPtr privconn = pool->conn->privateData;
5502
    virStoragePoolObjPtr obj;
5503
    char *ret = NULL;
5504

E
Eric Blake 已提交
5505 5506
    virCheckFlags(0, NULL);

5507
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
5508
        return NULL;
5509

5510
    ret = virStoragePoolDefFormat(virStoragePoolObjGetDef(obj));
5511

5512
    virStoragePoolObjEndAPI(&obj);
5513
    return ret;
C
Cole Robinson 已提交
5514 5515
}

5516

C
Cole Robinson 已提交
5517
static int
5518
testStoragePoolGetAutostart(virStoragePoolPtr pool,
5519 5520
                            int *autostart)
{
5521
    testDriverPtr privconn = pool->conn->privateData;
5522
    virStoragePoolObjPtr obj;
5523

5524
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
5525
        return -1;
C
Cole Robinson 已提交
5526

5527
    if (!virStoragePoolObjGetConfigFile(obj))
C
Cole Robinson 已提交
5528
        *autostart = 0;
5529
    else
5530
        *autostart = virStoragePoolObjIsAutostart(obj) ? 1 : 0;
C
Cole Robinson 已提交
5531

5532
    virStoragePoolObjEndAPI(&obj);
5533
    return 0;
C
Cole Robinson 已提交
5534 5535
}

5536

C
Cole Robinson 已提交
5537
static int
5538
testStoragePoolSetAutostart(virStoragePoolPtr pool,
5539 5540
                            int autostart)
{
5541
    testDriverPtr privconn = pool->conn->privateData;
5542
    virStoragePoolObjPtr obj;
5543
    bool new_autostart = (autostart != 0);
5544
    int ret = -1;
5545

5546
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
5547
        return -1;
C
Cole Robinson 已提交
5548

5549
    if (!virStoragePoolObjGetConfigFile(obj)) {
5550 5551
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("pool has no config file"));
5552
        goto cleanup;
C
Cole Robinson 已提交
5553 5554
    }

5555
    virStoragePoolObjSetAutostart(obj, new_autostart);
5556 5557
    ret = 0;

5558
 cleanup:
5559
    virStoragePoolObjEndAPI(&obj);
5560
    return ret;
C
Cole Robinson 已提交
5561 5562 5563 5564
}


static int
5565 5566
testStoragePoolNumOfVolumes(virStoragePoolPtr pool)
{
5567
    testDriverPtr privconn = pool->conn->privateData;
5568
    virStoragePoolObjPtr obj;
5569
    int ret = -1;
5570

5571 5572
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
5573

5574
    ret = virStoragePoolObjNumOfVolumes(obj, pool->conn, NULL);
5575

5576
    virStoragePoolObjEndAPI(&obj);
5577
    return ret;
C
Cole Robinson 已提交
5578 5579
}

5580

C
Cole Robinson 已提交
5581
static int
5582
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
5583
                           char **const names,
5584 5585
                           int maxnames)
{
5586
    testDriverPtr privconn = pool->conn->privateData;
5587
    virStoragePoolObjPtr obj;
5588
    int n = -1;
5589

5590
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
5591
        return -1;
5592

5593
    n = virStoragePoolObjVolumeGetNames(obj, pool->conn, NULL, names, maxnames);
C
Cole Robinson 已提交
5594

5595
    virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
5596 5597 5598
    return n;
}

5599

5600
static int
5601
testStoragePoolListAllVolumes(virStoragePoolPtr pool,
5602
                              virStorageVolPtr **vols,
5603 5604
                              unsigned int flags)
{
5605 5606
    testDriverPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr obj;
5607 5608 5609 5610
    int ret = -1;

    virCheckFlags(0, -1);

5611
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
5612
        return -1;
5613

5614
    if (!virStoragePoolObjIsActive(obj)) {
5615 5616 5617 5618 5619
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("storage pool is not active"));
        goto cleanup;
    }

5620
    ret = virStoragePoolObjVolumeListExport(pool->conn, obj, vols, NULL);
5621 5622

 cleanup:
5623
    virStoragePoolObjEndAPI(&obj);
5624 5625 5626

    return ret;
}
C
Cole Robinson 已提交
5627

5628

5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643
static virStorageVolDefPtr
testStorageVolDefFindByName(virStoragePoolObjPtr obj,
                            const char *name)
{
    virStorageVolDefPtr privvol;

    if (!(privvol = virStorageVolDefFindByName(obj, name))) {
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"), name);
    }

    return privvol;
}


C
Cole Robinson 已提交
5644
static virStorageVolPtr
5645
testStorageVolLookupByName(virStoragePoolPtr pool,
5646
                           const char *name)
5647
{
5648
    testDriverPtr privconn = pool->conn->privateData;
5649
    virStoragePoolObjPtr obj;
5650
    virStoragePoolDefPtr def;
5651
    virStorageVolDefPtr privvol;
5652
    virStorageVolPtr ret = NULL;
5653

5654 5655
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return NULL;
5656
    def = virStoragePoolObjGetDef(obj);
5657

5658
    if (!(privvol = testStorageVolDefFindByName(obj, name)))
5659
        goto cleanup;
C
Cole Robinson 已提交
5660

5661
    ret = virGetStorageVol(pool->conn, def->name,
5662 5663
                           privvol->name, privvol->key,
                           NULL, NULL);
5664

5665
 cleanup:
5666
    virStoragePoolObjEndAPI(&obj);
5667
    return ret;
C
Cole Robinson 已提交
5668 5669 5670
}


5671 5672 5673 5674 5675 5676 5677 5678 5679 5680
struct storageVolLookupData {
    const char *key;
    const char *path;
    virStorageVolDefPtr voldef;
};

static bool
testStorageVolLookupByKeyCallback(virStoragePoolObjPtr obj,
                                  const void *opaque)
{
5681
    struct storageVolLookupData *data = (struct storageVolLookupData *)opaque;
5682 5683 5684 5685 5686 5687 5688 5689

    if (virStoragePoolObjIsActive(obj))
        data->voldef = virStorageVolDefFindByKey(obj, data->key);

    return !!data->voldef;
}


C
Cole Robinson 已提交
5690
static virStorageVolPtr
5691
testStorageVolLookupByKey(virConnectPtr conn,
5692 5693
                          const char *key)
{
5694
    testDriverPtr privconn = conn->privateData;
5695
    virStoragePoolObjPtr obj;
5696
    virStoragePoolDefPtr def;
5697
    struct storageVolLookupData data = {
5698
        .key = key, .voldef = NULL };
5699
    virStorageVolPtr vol = NULL;
C
Cole Robinson 已提交
5700

5701
    virObjectLock(privconn);
5702
    if ((obj = virStoragePoolObjListSearch(privconn->pools,
5703 5704
                                           testStorageVolLookupByKeyCallback,
                                           &data)) && data.voldef) {
5705
        def = virStoragePoolObjGetDef(obj);
5706 5707 5708
        vol = virGetStorageVol(conn, def->name,
                               data.voldef->name, data.voldef->key,
                               NULL, NULL);
5709
        virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
5710
    }
5711
    virObjectUnlock(privconn);
C
Cole Robinson 已提交
5712

5713
    if (!vol)
5714 5715
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching key '%s'"), key);
5716

5717 5718 5719 5720 5721 5722 5723 5724
    return vol;
}


static bool
testStorageVolLookupByPathCallback(virStoragePoolObjPtr obj,
                                   const void *opaque)
{
5725
    struct storageVolLookupData *data = (struct storageVolLookupData *)opaque;
5726 5727 5728 5729 5730

    if (virStoragePoolObjIsActive(obj))
        data->voldef = virStorageVolDefFindByPath(obj, data->path);

    return !!data->voldef;
C
Cole Robinson 已提交
5731 5732
}

5733

C
Cole Robinson 已提交
5734
static virStorageVolPtr
5735
testStorageVolLookupByPath(virConnectPtr conn,
5736 5737
                           const char *path)
{
5738
    testDriverPtr privconn = conn->privateData;
5739
    virStoragePoolObjPtr obj;
5740
    virStoragePoolDefPtr def;
5741
    struct storageVolLookupData data = {
5742
        .path = path, .voldef = NULL };
5743
    virStorageVolPtr vol = NULL;
C
Cole Robinson 已提交
5744

5745
    virObjectLock(privconn);
5746
    if ((obj = virStoragePoolObjListSearch(privconn->pools,
5747 5748
                                           testStorageVolLookupByPathCallback,
                                           &data)) && data.voldef) {
5749
        def = virStoragePoolObjGetDef(obj);
5750 5751 5752
        vol = virGetStorageVol(conn, def->name,
                               data.voldef->name, data.voldef->key,
                               NULL, NULL);
5753
        virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
5754
    }
5755
    virObjectUnlock(privconn);
C
Cole Robinson 已提交
5756

5757
    if (!vol)
5758 5759
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching path '%s'"), path);
5760

5761
    return vol;
C
Cole Robinson 已提交
5762 5763
}

5764

C
Cole Robinson 已提交
5765
static virStorageVolPtr
5766 5767 5768
testStorageVolCreateXML(virStoragePoolPtr pool,
                        const char *xmldesc,
                        unsigned int flags)
E
Eric Blake 已提交
5769
{
5770
    testDriverPtr privconn = pool->conn->privateData;
5771
    virStoragePoolObjPtr obj;
5772
    virStoragePoolDefPtr def;
5773
    virStorageVolPtr ret = NULL;
5774
    VIR_AUTOPTR(virStorageVolDef) privvol = NULL;
5775

E
Eric Blake 已提交
5776 5777
    virCheckFlags(0, NULL);

5778 5779
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return NULL;
5780
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
5781

5782
    privvol = virStorageVolDefParseString(def, xmldesc, 0);
5783
    if (privvol == NULL)
5784
        goto cleanup;
5785

5786
    if (virStorageVolDefFindByName(obj, privvol->name)) {
5787 5788
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
5789
        goto cleanup;
C
Cole Robinson 已提交
5790 5791 5792
    }

    /* Make sure enough space */
5793 5794
    if ((def->allocation + privvol->target.allocation) >
         def->capacity) {
5795 5796 5797
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
5798
        goto cleanup;
C
Cole Robinson 已提交
5799 5800
    }

5801
    if (virAsprintf(&privvol->target.path, "%s/%s",
5802
                    def->target.path, privvol->name) < 0)
5803
        goto cleanup;
C
Cole Robinson 已提交
5804

5805
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
5806
        virStoragePoolObjAddVol(obj, privvol) < 0)
5807
        goto cleanup;
C
Cole Robinson 已提交
5808

5809 5810
    def->allocation += privvol->target.allocation;
    def->available = (def->capacity - def->allocation);
C
Cole Robinson 已提交
5811

5812
    ret = virGetStorageVol(pool->conn, def->name,
5813 5814
                           privvol->name, privvol->key,
                           NULL, NULL);
5815
    privvol = NULL;
5816

5817
 cleanup:
5818
    virStoragePoolObjEndAPI(&obj);
5819
    return ret;
C
Cole Robinson 已提交
5820 5821
}

5822

5823
static virStorageVolPtr
5824 5825 5826 5827
testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
                            const char *xmldesc,
                            virStorageVolPtr clonevol,
                            unsigned int flags)
E
Eric Blake 已提交
5828
{
5829
    testDriverPtr privconn = pool->conn->privateData;
5830
    virStoragePoolObjPtr obj;
5831
    virStoragePoolDefPtr def;
5832
    virStorageVolDefPtr origvol = NULL;
5833
    virStorageVolPtr ret = NULL;
5834
    VIR_AUTOPTR(virStorageVolDef) privvol = NULL;
5835

E
Eric Blake 已提交
5836 5837
    virCheckFlags(0, NULL);

5838 5839
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return NULL;
5840
    def = virStoragePoolObjGetDef(obj);
5841

5842
    privvol = virStorageVolDefParseString(def, xmldesc, 0);
5843 5844 5845
    if (privvol == NULL)
        goto cleanup;

5846
    if (virStorageVolDefFindByName(obj, privvol->name)) {
5847 5848
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
5849 5850 5851
        goto cleanup;
    }

5852
    origvol = virStorageVolDefFindByName(obj, clonevol->name);
5853
    if (!origvol) {
5854 5855 5856
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       clonevol->name);
5857 5858 5859 5860
        goto cleanup;
    }

    /* Make sure enough space */
5861
    if ((def->allocation + privvol->target.allocation) > def->capacity) {
5862 5863 5864
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
5865 5866
        goto cleanup;
    }
5867
    def->available = (def->capacity - def->allocation);
5868

5869
    if (virAsprintf(&privvol->target.path, "%s/%s",
5870
                    def->target.path, privvol->name) < 0)
5871 5872
        goto cleanup;

5873
    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
5874
        virStoragePoolObjAddVol(obj, privvol) < 0)
5875 5876
        goto cleanup;

5877 5878
    def->allocation += privvol->target.allocation;
    def->available = (def->capacity - def->allocation);
5879

5880
    ret = virGetStorageVol(pool->conn, def->name,
5881 5882
                           privvol->name, privvol->key,
                           NULL, NULL);
5883 5884
    privvol = NULL;

5885
 cleanup:
5886
    virStoragePoolObjEndAPI(&obj);
5887 5888 5889
    return ret;
}

5890

C
Cole Robinson 已提交
5891
static int
5892 5893
testStorageVolDelete(virStorageVolPtr vol,
                     unsigned int flags)
E
Eric Blake 已提交
5894
{
5895
    testDriverPtr privconn = vol->conn->privateData;
5896
    virStoragePoolObjPtr obj;
5897
    virStoragePoolDefPtr def;
5898
    virStorageVolDefPtr privvol;
5899
    int ret = -1;
C
Cole Robinson 已提交
5900

E
Eric Blake 已提交
5901 5902
    virCheckFlags(0, -1);

5903 5904
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return -1;
5905
    def = virStoragePoolObjGetDef(obj);
5906

5907
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
5908
        goto cleanup;
5909

5910 5911
    def->allocation -= privvol->target.allocation;
    def->available = (def->capacity - def->allocation);
C
Cole Robinson 已提交
5912

5913
    virStoragePoolObjRemoveVol(obj, privvol);
C
Cole Robinson 已提交
5914

5915
    ret = 0;
C
Cole Robinson 已提交
5916

5917
 cleanup:
5918
    virStoragePoolObjEndAPI(&obj);
5919
    return ret;
C
Cole Robinson 已提交
5920 5921 5922
}


5923 5924
static int
testStorageVolumeTypeForPool(int pooltype)
5925
{
5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947
    switch ((virStoragePoolType) pooltype) {
    case VIR_STORAGE_POOL_DIR:
    case VIR_STORAGE_POOL_FS:
    case VIR_STORAGE_POOL_NETFS:
    case VIR_STORAGE_POOL_VSTORAGE:
        return VIR_STORAGE_VOL_FILE;
    case VIR_STORAGE_POOL_SHEEPDOG:
    case VIR_STORAGE_POOL_ISCSI_DIRECT:
    case VIR_STORAGE_POOL_GLUSTER:
    case VIR_STORAGE_POOL_RBD:
        return VIR_STORAGE_VOL_NETWORK;
    case VIR_STORAGE_POOL_LOGICAL:
    case VIR_STORAGE_POOL_DISK:
    case VIR_STORAGE_POOL_MPATH:
    case VIR_STORAGE_POOL_ISCSI:
    case VIR_STORAGE_POOL_SCSI:
    case VIR_STORAGE_POOL_ZFS:
        return VIR_STORAGE_VOL_BLOCK;
    case VIR_STORAGE_POOL_LAST:
    default:
        virReportEnumRangeError(virStoragePoolType, pooltype);
        return -1;
C
Cole Robinson 已提交
5948 5949 5950
    }
}

5951

C
Cole Robinson 已提交
5952
static int
5953
testStorageVolGetInfo(virStorageVolPtr vol,
5954 5955
                      virStorageVolInfoPtr info)
{
5956
    testDriverPtr privconn = vol->conn->privateData;
5957
    virStoragePoolObjPtr obj;
5958
    virStoragePoolDefPtr def;
5959
    virStorageVolDefPtr privvol;
5960
    int ret = -1;
5961

5962 5963
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return -1;
5964
    def = virStoragePoolObjGetDef(obj);
5965

5966
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
5967
        goto cleanup;
5968

C
Cole Robinson 已提交
5969
    memset(info, 0, sizeof(*info));
5970 5971
    if ((info->type = testStorageVolumeTypeForPool(def->type)) < 0)
        goto cleanup;
5972 5973
    info->capacity = privvol->target.capacity;
    info->allocation = privvol->target.allocation;
5974
    ret = 0;
C
Cole Robinson 已提交
5975

5976
 cleanup:
5977
    virStoragePoolObjEndAPI(&obj);
5978
    return ret;
C
Cole Robinson 已提交
5979 5980
}

5981

C
Cole Robinson 已提交
5982
static char *
5983 5984
testStorageVolGetXMLDesc(virStorageVolPtr vol,
                         unsigned int flags)
E
Eric Blake 已提交
5985
{
5986
    testDriverPtr privconn = vol->conn->privateData;
5987
    virStoragePoolObjPtr obj;
5988
    virStorageVolDefPtr privvol;
5989
    char *ret = NULL;
5990

E
Eric Blake 已提交
5991 5992
    virCheckFlags(0, NULL);

5993 5994
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return NULL;
5995

5996
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
5997
        goto cleanup;
C
Cole Robinson 已提交
5998

5999
    ret = virStorageVolDefFormat(virStoragePoolObjGetDef(obj), privvol);
6000

6001
 cleanup:
6002
    virStoragePoolObjEndAPI(&obj);
6003
    return ret;
C
Cole Robinson 已提交
6004 6005
}

6006

C
Cole Robinson 已提交
6007
static char *
6008 6009
testStorageVolGetPath(virStorageVolPtr vol)
{
6010
    testDriverPtr privconn = vol->conn->privateData;
6011
    virStoragePoolObjPtr obj;
6012
    virStorageVolDefPtr privvol;
6013
    char *ret = NULL;
6014

6015 6016
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return NULL;
6017

6018
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
6019
        goto cleanup;
6020

6021
    ignore_value(VIR_STRDUP(ret, privvol->target.path));
6022

6023
 cleanup:
6024
    virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
6025 6026 6027
    return ret;
}

6028

6029
/* Node device implementations */
6030

6031 6032 6033 6034 6035 6036
static virNodeDeviceObjPtr
testNodeDeviceObjFindByName(testDriverPtr driver,
                            const char *name)
{
    virNodeDeviceObjPtr obj;

6037
    if (!(obj = virNodeDeviceObjListFindByName(driver->devs, name)))
6038 6039 6040 6041 6042 6043 6044 6045
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       name);

    return obj;
}


6046 6047 6048
static int
testNodeNumOfDevices(virConnectPtr conn,
                     const char *cap,
E
Eric Blake 已提交
6049
                     unsigned int flags)
6050
{
6051
    testDriverPtr driver = conn->privateData;
6052

E
Eric Blake 已提交
6053 6054
    virCheckFlags(0, -1);

6055
    return virNodeDeviceObjListNumOfDevices(driver->devs, conn, cap, NULL);
6056 6057
}

6058

6059 6060 6061 6062 6063
static int
testNodeListDevices(virConnectPtr conn,
                    const char *cap,
                    char **const names,
                    int maxnames,
E
Eric Blake 已提交
6064
                    unsigned int flags)
6065
{
6066
    testDriverPtr driver = conn->privateData;
6067

E
Eric Blake 已提交
6068 6069
    virCheckFlags(0, -1);

6070 6071
    return virNodeDeviceObjListGetNames(driver->devs, conn, NULL,
                                        cap, names, maxnames);
6072 6073
}

6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085
static int
testConnectListAllNodeDevices(virConnectPtr conn,
                              virNodeDevicePtr **devices,
                              unsigned int flags)
{
    testDriverPtr driver = conn->privateData;

    virCheckFlags(VIR_CONNECT_LIST_NODE_DEVICES_FILTERS_CAP, -1);

    return virNodeDeviceObjListExport(conn, driver->devs, devices,
                                      NULL, flags);
}
6086

6087 6088 6089
static virNodeDevicePtr
testNodeDeviceLookupByName(virConnectPtr conn, const char *name)
{
6090
    testDriverPtr driver = conn->privateData;
6091
    virNodeDeviceObjPtr obj;
6092
    virNodeDeviceDefPtr def;
6093 6094
    virNodeDevicePtr ret = NULL;

6095
    if (!(obj = testNodeDeviceObjFindByName(driver, name)))
6096
        return NULL;
6097
    def = virNodeDeviceObjGetDef(obj);
6098

6099
    if ((ret = virGetNodeDevice(conn, name))) {
6100
        if (VIR_STRDUP(ret->parentName, def->parent) < 0) {
6101
            virObjectUnref(ret);
6102 6103
            ret = NULL;
        }
6104
    }
6105

6106
    virNodeDeviceObjEndAPI(&obj);
6107 6108 6109 6110
    return ret;
}

static char *
6111
testNodeDeviceGetXMLDesc(virNodeDevicePtr dev,
E
Eric Blake 已提交
6112
                         unsigned int flags)
6113
{
6114
    testDriverPtr driver = dev->conn->privateData;
6115 6116 6117
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

E
Eric Blake 已提交
6118 6119
    virCheckFlags(0, NULL);

6120
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
6121
        return NULL;
6122

6123
    ret = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(obj));
6124

6125
    virNodeDeviceObjEndAPI(&obj);
6126 6127 6128 6129 6130 6131
    return ret;
}

static char *
testNodeDeviceGetParent(virNodeDevicePtr dev)
{
6132
    testDriverPtr driver = dev->conn->privateData;
6133
    virNodeDeviceObjPtr obj;
6134
    virNodeDeviceDefPtr def;
6135 6136
    char *ret = NULL;

6137
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
6138
        return NULL;
6139
    def = virNodeDeviceObjGetDef(obj);
6140

6141 6142
    if (def->parent) {
        ignore_value(VIR_STRDUP(ret, def->parent));
6143
    } else {
6144 6145
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no parent for this device"));
6146 6147
    }

6148
    virNodeDeviceObjEndAPI(&obj);
6149 6150 6151
    return ret;
}

6152

6153 6154 6155
static int
testNodeDeviceNumOfCaps(virNodeDevicePtr dev)
{
6156
    testDriverPtr driver = dev->conn->privateData;
6157
    virNodeDeviceObjPtr obj;
6158
    virNodeDeviceDefPtr def;
6159 6160 6161
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;

6162
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
6163
        return -1;
6164
    def = virNodeDeviceObjGetDef(obj);
6165

6166
    for (caps = def->caps; caps; caps = caps->next)
6167 6168
        ++ncaps;

6169
    virNodeDeviceObjEndAPI(&obj);
6170
    return ncaps;
6171 6172 6173 6174 6175 6176
}


static int
testNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
6177
    testDriverPtr driver = dev->conn->privateData;
6178
    virNodeDeviceObjPtr obj;
6179
    virNodeDeviceDefPtr def;
6180 6181 6182
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;

6183
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
6184
        return -1;
6185
    def = virNodeDeviceObjGetDef(obj);
6186

6187
    for (caps = def->caps; caps && ncaps < maxnames; caps = caps->next) {
6188 6189 6190 6191
        if (VIR_STRDUP(names[ncaps],
                       virNodeDevCapTypeToString(caps->data.type)) < 0)
            goto error;
        ncaps++;
6192 6193
    }

6194
    virNodeDeviceObjEndAPI(&obj);
6195 6196 6197 6198 6199
    return ncaps;

 error:
    while (--ncaps >= 0)
        VIR_FREE(names[ncaps]);
6200
    virNodeDeviceObjEndAPI(&obj);
6201
    return -1;
6202 6203
}

6204

6205 6206
static virNodeDeviceObjPtr
testNodeDeviceMockCreateVport(testDriverPtr driver,
6207
                              const char *wwnn,
6208
                              const char *wwpn)
6209
{
6210
    virNodeDeviceDefPtr def = NULL;
6211
    virNodeDevCapsDefPtr caps;
6212
    virNodeDeviceObjPtr obj = NULL, objcopy = NULL;
6213
    virNodeDeviceDefPtr objdef;
6214
    virObjectEventPtr event = NULL;
6215
    VIR_AUTOFREE(char *) xml = NULL;
6216

6217 6218 6219 6220 6221 6222 6223 6224 6225
    /* In the real code, we'd call virVHBAManageVport which would take the
     * wwnn/wwpn from the input XML in order to call the "vport_create"
     * function for the parent. That in turn would set off a sequence of
     * events resulting in the creation of a vHBA scsi_hostN in the
     * node device objects list using the "next" host number with the
     * wwnn/wwpn from the input XML. The following will mock this by
     * using the scsi_host11 definition, changing the name and the
     * scsi_host capability fields before calling virNodeDeviceAssignDef
     * to add the def to the node device objects list. */
6226 6227
    if (!(objcopy = virNodeDeviceObjListFindByName(driver->devs,
                                                   "scsi_host11")))
6228 6229
        goto cleanup;

6230
    xml = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(objcopy));
6231
    virNodeDeviceObjEndAPI(&objcopy);
6232 6233 6234 6235
    if (!xml)
        goto cleanup;

    if (!(def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL)))
6236 6237
        goto cleanup;

6238
    VIR_FREE(def->name);
6239
    if (VIR_STRDUP(def->name, "scsi_host12") < 0)
6240 6241
        goto cleanup;

6242 6243 6244
    /* Find the 'scsi_host' cap and alter the host # and unique_id and
     * then for the 'fc_host' capability modify the wwnn/wwpn to be that
     * of the input XML. */
6245 6246
    caps = def->caps;
    while (caps) {
6247
        if (caps->data.type != VIR_NODE_DEV_CAP_SCSI_HOST)
6248 6249
            continue;

6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263
        /* For the "fc_host" cap - change the wwnn/wwpn to match the input */
        if (caps->data.scsi_host.flags & VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST) {
            VIR_FREE(caps->data.scsi_host.wwnn);
            VIR_FREE(caps->data.scsi_host.wwpn);
            if (VIR_STRDUP(caps->data.scsi_host.wwnn, wwnn) < 0 ||
                VIR_STRDUP(caps->data.scsi_host.wwpn, wwpn) < 0)
                goto cleanup;
        } else {
            /* For the "scsi_host" cap, increment our host and unique_id to
             * give the appearance that something new was created - then add
             * that to the node device driver */
            caps->data.scsi_host.host++;
            caps->data.scsi_host.unique_id++;
        }
6264 6265 6266
        caps = caps->next;
    }

6267
    if (!(obj = virNodeDeviceObjListAssignDef(driver->devs, def)))
6268
        goto cleanup;
6269
    virNodeDeviceObjSetSkipUpdateCaps(obj, true);
6270
    def = NULL;
6271
    objdef = virNodeDeviceObjGetDef(obj);
6272

6273
    event = virNodeDeviceEventLifecycleNew(objdef->name,
6274 6275
                                           VIR_NODE_DEVICE_EVENT_CREATED,
                                           0);
6276
    virObjectEventStateQueue(driver->eventState, event);
6277 6278

 cleanup:
6279 6280
    virNodeDeviceDefFree(def);
    return obj;
6281 6282 6283 6284 6285 6286 6287 6288 6289 6290
}


static virNodeDevicePtr
testNodeDeviceCreateXML(virConnectPtr conn,
                        const char *xmlDesc,
                        unsigned int flags)
{
    testDriverPtr driver = conn->privateData;
    virNodeDeviceDefPtr def = NULL;
6291 6292
    virNodeDevicePtr dev = NULL, ret = NULL;
    virNodeDeviceObjPtr obj = NULL;
6293
    virNodeDeviceDefPtr objdef;
6294 6295
    VIR_AUTOFREE(char *) wwnn = NULL;
    VIR_AUTOFREE(char *) wwpn = NULL;
6296 6297 6298 6299 6300 6301

    virCheckFlags(0, NULL);

    if (!(def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, NULL)))
        goto cleanup;

6302 6303 6304
    /* We run this simply for validation - it essentially validates that
     * the input XML either has a wwnn/wwpn or virNodeDevCapSCSIHostParseXML
     * generated a wwnn/wwpn */
6305 6306 6307
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) < 0)
        goto cleanup;

6308 6309 6310
    /* Unlike the "real" code we don't need the parent_host in order to
     * call virVHBAManageVport, but still let's make sure the code finds
     * something valid and no one messed up the mock environment. */
6311
    if (virNodeDeviceObjListGetParentHost(driver->devs, def) < 0)
6312 6313 6314 6315
        goto cleanup;

    /* In the real code, we'd call virVHBAManageVport followed by
     * find_new_device, but we cannot do that here since we're not
6316 6317 6318
     * mocking udev. The mock routine will copy an existing vHBA and
     * rename a few fields to mock that. So in order to allow that to
     * work properly, we need to drop our lock */
6319 6320
    if (!(obj = testNodeDeviceMockCreateVport(driver, wwnn, wwpn)))
        goto cleanup;
6321
    objdef = virNodeDeviceObjGetDef(obj);
6322

6323
    if (!(dev = virGetNodeDevice(conn, objdef->name)))
6324 6325
        goto cleanup;

6326 6327
    VIR_FREE(dev->parentName);
    if (VIR_STRDUP(dev->parentName, def->parent) < 0)
6328 6329
        goto cleanup;

6330
    VIR_STEAL_PTR(ret, dev);
6331

6332
 cleanup:
6333
    virNodeDeviceObjEndAPI(&obj);
6334
    virNodeDeviceDefFree(def);
6335 6336
    virObjectUnref(dev);
    return ret;
6337 6338 6339 6340 6341 6342
}

static int
testNodeDeviceDestroy(virNodeDevicePtr dev)
{
    int ret = 0;
6343
    testDriverPtr driver = dev->conn->privateData;
6344
    virNodeDeviceObjPtr obj = NULL;
6345
    virNodeDeviceObjPtr parentobj = NULL;
6346
    virNodeDeviceDefPtr def;
6347
    virObjectEventPtr event = NULL;
6348 6349
    VIR_AUTOFREE(char *) wwnn = NULL;
    VIR_AUTOFREE(char *) wwpn = NULL;
6350

6351
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
6352
        return -1;
6353
    def = virNodeDeviceObjGetDef(obj);
6354

6355
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) == -1)
6356
        goto cleanup;
6357

6358 6359 6360 6361
    /* Unlike the real code we cannot run into the udevAddOneDevice race
     * which would replace obj->def, so no need to save off the parent,
     * but do need to drop the @obj lock so that the FindByName code doesn't
     * deadlock on ourselves */
6362
    virObjectUnlock(obj);
6363

6364 6365 6366 6367 6368 6369
    /* We do this just for basic validation and throw away the parentobj
     * since there's no vport_delete to be run */
    if (!(parentobj = virNodeDeviceObjListFindByName(driver->devs,
                                                     def->parent))) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("cannot find parent '%s' definition"), def->parent);
6370
        virObjectLock(obj);
6371
        goto cleanup;
6372
    }
6373
    virNodeDeviceObjEndAPI(&parentobj);
6374

6375 6376 6377 6378
    event = virNodeDeviceEventLifecycleNew(dev->name,
                                           VIR_NODE_DEVICE_EVENT_DELETED,
                                           0);

6379
    virObjectLock(obj);
6380
    virNodeDeviceObjListRemove(driver->devs, obj);
6381
    virObjectUnref(obj);
6382
    obj = NULL;
6383

6384
 cleanup:
6385
    virNodeDeviceObjEndAPI(&obj);
6386
    virObjectEventStateQueue(driver->eventState, event);
6387 6388 6389
    return ret;
}

6390 6391

/* Domain event implementations */
6392
static int
6393 6394 6395 6396
testConnectDomainEventRegister(virConnectPtr conn,
                               virConnectDomainEventCallback callback,
                               void *opaque,
                               virFreeCallback freecb)
6397
{
6398
    testDriverPtr driver = conn->privateData;
6399
    int ret = 0;
6400

6401
    if (virDomainEventStateRegister(conn, driver->eventState,
6402 6403
                                    callback, opaque, freecb) < 0)
        ret = -1;
6404 6405 6406 6407

    return ret;
}

6408

6409
static int
6410 6411
testConnectDomainEventDeregister(virConnectPtr conn,
                                 virConnectDomainEventCallback callback)
6412
{
6413
    testDriverPtr driver = conn->privateData;
6414
    int ret = 0;
6415

6416
    if (virDomainEventStateDeregister(conn, driver->eventState,
6417 6418
                                      callback) < 0)
        ret = -1;
6419 6420 6421 6422

    return ret;
}

6423 6424

static int
6425 6426 6427 6428 6429 6430
testConnectDomainEventRegisterAny(virConnectPtr conn,
                                  virDomainPtr dom,
                                  int eventID,
                                  virConnectDomainEventGenericCallback callback,
                                  void *opaque,
                                  virFreeCallback freecb)
6431
{
6432
    testDriverPtr driver = conn->privateData;
6433 6434
    int ret;

6435
    if (virDomainEventStateRegisterID(conn, driver->eventState,
6436 6437
                                      dom, eventID,
                                      callback, opaque, freecb, &ret) < 0)
6438
        ret = -1;
6439 6440 6441 6442 6443

    return ret;
}

static int
6444 6445
testConnectDomainEventDeregisterAny(virConnectPtr conn,
                                    int callbackID)
6446
{
6447
    testDriverPtr driver = conn->privateData;
6448
    int ret = 0;
6449

6450
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
6451
                                        callbackID, true) < 0)
6452
        ret = -1;
6453 6454 6455 6456 6457

    return ret;
}


6458 6459 6460 6461 6462 6463 6464 6465
static int
testConnectNetworkEventRegisterAny(virConnectPtr conn,
                                   virNetworkPtr net,
                                   int eventID,
                                   virConnectNetworkEventGenericCallback callback,
                                   void *opaque,
                                   virFreeCallback freecb)
{
6466
    testDriverPtr driver = conn->privateData;
6467 6468
    int ret;

6469
    if (virNetworkEventStateRegisterID(conn, driver->eventState,
6470
                                       net, eventID, callback,
6471 6472 6473 6474 6475 6476 6477 6478 6479 6480
                                       opaque, freecb, &ret) < 0)
        ret = -1;

    return ret;
}

static int
testConnectNetworkEventDeregisterAny(virConnectPtr conn,
                                     int callbackID)
{
6481
    testDriverPtr driver = conn->privateData;
6482
    int ret = 0;
6483

6484
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
6485
                                        callbackID, true) < 0)
6486
        ret = -1;
6487 6488 6489 6490

    return ret;
}

6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517
static int
testConnectStoragePoolEventRegisterAny(virConnectPtr conn,
                                       virStoragePoolPtr pool,
                                       int eventID,
                                       virConnectStoragePoolEventGenericCallback callback,
                                       void *opaque,
                                       virFreeCallback freecb)
{
    testDriverPtr driver = conn->privateData;
    int ret;

    if (virStoragePoolEventStateRegisterID(conn, driver->eventState,
                                           pool, eventID, callback,
                                           opaque, freecb, &ret) < 0)
        ret = -1;

    return ret;
}

static int
testConnectStoragePoolEventDeregisterAny(virConnectPtr conn,
                                         int callbackID)
{
    testDriverPtr driver = conn->privateData;
    int ret = 0;

    if (virObjectEventStateDeregisterID(conn, driver->eventState,
6518
                                        callbackID, true) < 0)
6519 6520 6521 6522 6523
        ret = -1;

    return ret;
}

6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550
static int
testConnectNodeDeviceEventRegisterAny(virConnectPtr conn,
                                      virNodeDevicePtr dev,
                                      int eventID,
                                      virConnectNodeDeviceEventGenericCallback callback,
                                      void *opaque,
                                      virFreeCallback freecb)
{
    testDriverPtr driver = conn->privateData;
    int ret;

    if (virNodeDeviceEventStateRegisterID(conn, driver->eventState,
                                          dev, eventID, callback,
                                          opaque, freecb, &ret) < 0)
        ret = -1;

    return ret;
}

static int
testConnectNodeDeviceEventDeregisterAny(virConnectPtr conn,
                                        int callbackID)
{
    testDriverPtr driver = conn->privateData;
    int ret = 0;

    if (virObjectEventStateDeregisterID(conn, driver->eventState,
6551
                                        callbackID, true) < 0)
6552 6553 6554 6555 6556
        ret = -1;

    return ret;
}

6557 6558 6559
static int testConnectListAllDomains(virConnectPtr conn,
                                     virDomainPtr **domains,
                                     unsigned int flags)
6560
{
6561
    testDriverPtr privconn = conn->privateData;
6562

O
Osier Yang 已提交
6563
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
6564

6565 6566
    return virDomainObjListExport(privconn->domains, conn, domains,
                                  NULL, flags);
6567 6568
}

6569
static int
P
Peter Krempa 已提交
6570
testNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,
6571 6572 6573 6574 6575 6576 6577
                  unsigned char **cpumap,
                  unsigned int *online,
                  unsigned int flags)
{
    virCheckFlags(0, -1);

    if (cpumap) {
6578
        if (VIR_ALLOC_N(*cpumap, 1) < 0)
P
Peter Krempa 已提交
6579
            return -1;
6580 6581 6582 6583 6584 6585
        *cpumap[0] = 0x15;
    }

    if (online)
        *online = 3;

P
Peter Krempa 已提交
6586
    return  8;
6587 6588
}

6589 6590 6591 6592 6593 6594 6595 6596 6597 6598
static char *
testDomainScreenshot(virDomainPtr dom ATTRIBUTE_UNUSED,
                     virStreamPtr st,
                     unsigned int screen ATTRIBUTE_UNUSED,
                     unsigned int flags)
{
    char *ret = NULL;

    virCheckFlags(0, NULL);

6599
    if (VIR_STRDUP(ret, "image/png") < 0)
6600 6601
        return NULL;

D
Daniel P. Berrange 已提交
6602
    if (virFDStreamOpenFile(st, PKGDATADIR "/test-screenshot.png", 0, 0, O_RDONLY) < 0)
6603 6604 6605 6606 6607
        VIR_FREE(ret);

    return ret;
}

6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646

static int
testDomainSendKey(virDomainPtr domain,
                  unsigned int codeset,
                  unsigned int holdtime ATTRIBUTE_UNUSED,
                  unsigned int *keycodes,
                  int nkeycodes,
                  unsigned int flags)
{
    int ret = -1;
    size_t i;
    virDomainObjPtr vm = NULL;

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(domain)))
        goto cleanup;

    if (virDomainObjCheckActive(vm) < 0)
        goto cleanup;

    for (i = 0; i < nkeycodes; i++) {
        if (virKeycodeValueTranslate(codeset, codeset, keycodes[i]) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("invalid keycode %u of %s codeset"),
                           keycodes[i],
                           virKeycodeSetTypeToString(codeset));
            goto cleanup;
        }
    }

    ret = 0;

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


6647 6648
static int
testConnectGetCPUModelNames(virConnectPtr conn ATTRIBUTE_UNUSED,
J
Jiri Denemark 已提交
6649
                            const char *archName,
6650 6651 6652
                            char ***models,
                            unsigned int flags)
{
J
Jiri Denemark 已提交
6653 6654
    virArch arch;

6655
    virCheckFlags(0, -1);
J
Jiri Denemark 已提交
6656 6657 6658 6659 6660 6661 6662 6663

    if (!(arch = virArchFromString(archName))) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("cannot find architecture %s"),
                       archName);
        return -1;
    }

J
Jiri Denemark 已提交
6664
    return virCPUGetModels(arch, models);
6665
}
6666

C
Cole Robinson 已提交
6667 6668 6669
static int
testDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
6670
    testDriverPtr privconn = dom->conn->privateData;
C
Cole Robinson 已提交
6671
    virDomainObjPtr vm = NULL;
6672
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
6673 6674 6675 6676 6677 6678
    int ret = -1;

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

6679 6680
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
6681

6682
    if (virDomainObjCheckActive(vm) < 0)
C
Cole Robinson 已提交
6683 6684 6685 6686 6687 6688 6689 6690 6691
        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);
6692
    event = virDomainEventLifecycleNewFromObj(vm,
C
Cole Robinson 已提交
6693 6694 6695 6696 6697
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
    vm->hasManagedSave = true;

    ret = 0;
6698
 cleanup:
6699
    virDomainObjEndAPI(&vm);
6700
    virObjectEventStateQueue(privconn->eventState, event);
C
Cole Robinson 已提交
6701 6702 6703 6704 6705 6706 6707 6708 6709

    return ret;
}


static int
testDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm;
6710
    int ret;
C
Cole Robinson 已提交
6711 6712 6713

    virCheckFlags(0, -1);

6714 6715
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
6716 6717

    ret = vm->hasManagedSave;
6718

6719
    virDomainObjEndAPI(&vm);
C
Cole Robinson 已提交
6720 6721 6722 6723 6724 6725 6726 6727 6728 6729
    return ret;
}

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

    virCheckFlags(0, -1);

6730 6731
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
6732 6733

    vm->hasManagedSave = false;
6734

6735
    virDomainObjEndAPI(&vm);
6736
    return 0;
C
Cole Robinson 已提交
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 6769 6770 6771 6772 6773 6774
static int
testDomainMemoryPeek(virDomainPtr dom,
                     unsigned long long start,
                     size_t size,
                     void *buffer,
                     unsigned int flags)
{
    int ret = -1;
    size_t i;
    unsigned char b = start;
    virDomainObjPtr vm = NULL;

    virCheckFlags(VIR_MEMORY_VIRTUAL | VIR_MEMORY_PHYSICAL, -1);

    if (flags != VIR_MEMORY_VIRTUAL && flags != VIR_MEMORY_PHYSICAL) {
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("flags parameter must be VIR_MEMORY_VIRTUAL or VIR_MEMORY_PHYSICAL"));
        goto cleanup;
    }

    if (!(vm = testDomObjFromDomain(dom)))
        goto cleanup;

    if (virDomainObjCheckActive(vm) < 0)
        goto cleanup;

    for (i = 0; i < size; i++)
        ((unsigned char *) buffer)[i] = b++;

    ret = 0;

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

C
Cole Robinson 已提交
6775

6776 6777 6778 6779
/*
 * Snapshot APIs
 */

6780
static virDomainMomentObjPtr
6781 6782 6783
testSnapObjFromName(virDomainObjPtr vm,
                    const char *name)
{
6784
    virDomainMomentObjPtr snap = NULL;
6785 6786 6787 6788 6789 6790 6791 6792
    snap = virDomainSnapshotFindByName(vm->snapshots, name);
    if (!snap)
        virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
                       _("no domain snapshot with matching name '%s'"),
                       name);
    return snap;
}

6793
static virDomainMomentObjPtr
6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809
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;
6810
    int n;
6811 6812

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
E
Eric Blake 已提交
6813
                  VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
6814 6815 6816
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6817
        return -1;
6818 6819 6820

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

6821
    virDomainObjEndAPI(&vm);
6822 6823 6824 6825 6826 6827 6828 6829 6830 6831
    return n;
}

static int
testDomainSnapshotListNames(virDomainPtr domain,
                            char **names,
                            int nameslen,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6832
    int n;
6833 6834

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
E
Eric Blake 已提交
6835
                  VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
6836 6837 6838
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6839
        return -1;
6840 6841 6842 6843

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

6844
    virDomainObjEndAPI(&vm);
6845 6846 6847 6848 6849 6850 6851 6852 6853
    return n;
}

static int
testDomainListAllSnapshots(virDomainPtr domain,
                           virDomainSnapshotPtr **snaps,
                           unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6854
    int n;
6855 6856

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
E
Eric Blake 已提交
6857
                  VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
6858 6859 6860
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6861
        return -1;
6862 6863 6864

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

6865
    virDomainObjEndAPI(&vm);
6866 6867 6868 6869 6870 6871 6872 6873 6874 6875
    return n;
}

static int
testDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
                                    char **names,
                                    int nameslen,
                                    unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6876
    virDomainMomentObjPtr snap = NULL;
6877 6878 6879
    int n = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
E
Eric Blake 已提交
6880
                  VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
6881 6882 6883
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6884
        return -1;
6885 6886 6887 6888 6889 6890 6891

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

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

6892
 cleanup:
6893
    virDomainObjEndAPI(&vm);
6894 6895 6896 6897 6898 6899 6900 6901
    return n;
}

static int
testDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot,
                              unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6902
    virDomainMomentObjPtr snap = NULL;
6903 6904 6905
    int n = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
E
Eric Blake 已提交
6906
                  VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
6907 6908 6909
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6910
        return -1;
6911 6912 6913 6914 6915 6916

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

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

6917
 cleanup:
6918
    virDomainObjEndAPI(&vm);
6919 6920 6921 6922 6923 6924 6925 6926 6927
    return n;
}

static int
testDomainSnapshotListAllChildren(virDomainSnapshotPtr snapshot,
                                  virDomainSnapshotPtr **snaps,
                                  unsigned int flags)
{
    virDomainObjPtr vm = NULL;
6928
    virDomainMomentObjPtr snap = NULL;
6929 6930 6931
    int n = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
E
Eric Blake 已提交
6932
                  VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
6933 6934 6935
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
6936
        return -1;
6937 6938 6939 6940 6941 6942 6943

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

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

6944
 cleanup:
6945
    virDomainObjEndAPI(&vm);
6946 6947 6948 6949 6950 6951 6952 6953 6954
    return n;
}

static virDomainSnapshotPtr
testDomainSnapshotLookupByName(virDomainPtr domain,
                               const char *name,
                               unsigned int flags)
{
    virDomainObjPtr vm;
6955
    virDomainMomentObjPtr snap = NULL;
6956 6957 6958 6959 6960
    virDomainSnapshotPtr snapshot = NULL;

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
6961
        return NULL;
6962 6963 6964 6965

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

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

6968
 cleanup:
6969
    virDomainObjEndAPI(&vm);
6970 6971 6972 6973 6974 6975 6976 6977
    return snapshot;
}

static int
testDomainHasCurrentSnapshot(virDomainPtr domain,
                             unsigned int flags)
{
    virDomainObjPtr vm;
6978
    int ret;
6979 6980 6981 6982

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(domain)))
6983
        return -1;
6984

6985
    ret = (virDomainSnapshotGetCurrent(vm->snapshots) != NULL);
6986

6987
    virDomainObjEndAPI(&vm);
6988 6989 6990 6991 6992 6993 6994 6995
    return ret;
}

static virDomainSnapshotPtr
testDomainSnapshotGetParent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm;
6996
    virDomainMomentObjPtr snap = NULL;
6997 6998 6999 7000 7001
    virDomainSnapshotPtr parent = NULL;

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
7002
        return NULL;
7003 7004 7005 7006

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

7007
    if (!snap->def->parent_name) {
7008 7009
        virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
                       _("snapshot '%s' does not have a parent"),
7010
                       snap->def->name);
7011 7012 7013
        goto cleanup;
    }

7014
    parent = virGetDomainSnapshot(snapshot->domain, snap->def->parent_name);
7015

7016
 cleanup:
7017
    virDomainObjEndAPI(&vm);
7018 7019 7020 7021 7022 7023 7024 7025 7026
    return parent;
}

static virDomainSnapshotPtr
testDomainSnapshotCurrent(virDomainPtr domain,
                          unsigned int flags)
{
    virDomainObjPtr vm;
    virDomainSnapshotPtr snapshot = NULL;
7027
    virDomainMomentObjPtr current;
7028 7029 7030 7031

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
7032
        return NULL;
7033

7034 7035
    current = virDomainSnapshotGetCurrent(vm->snapshots);
    if (!current) {
7036 7037 7038 7039 7040
        virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT, "%s",
                       _("the domain does not have a current snapshot"));
        goto cleanup;
    }

7041
    snapshot = virGetDomainSnapshot(domain, current->def->name);
7042

7043
 cleanup:
7044
    virDomainObjEndAPI(&vm);
7045 7046 7047 7048 7049 7050 7051 7052 7053
    return snapshot;
}

static char *
testDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
                             unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    char *xml = NULL;
7054
    virDomainMomentObjPtr snap = NULL;
7055
    char uuidstr[VIR_UUID_STRING_BUFLEN];
7056
    testDriverPtr privconn = snapshot->domain->conn->privateData;
7057

7058
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_XML_SECURE, NULL);
7059 7060

    if (!(vm = testDomObjFromSnapshot(snapshot)))
7061
        return NULL;
7062 7063 7064 7065 7066 7067

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

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

7068 7069
    xml = virDomainSnapshotDefFormat(uuidstr, virDomainSnapshotObjGetDef(snap),
                                     privconn->caps, privconn->xmlopt,
7070
                                     virDomainSnapshotFormatConvertXMLFlags(flags));
7071

7072
 cleanup:
7073
    virDomainObjEndAPI(&vm);
7074 7075 7076 7077 7078 7079 7080 7081
    return xml;
}

static int
testDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
7082 7083
    int ret = -1;
    virDomainMomentObjPtr snap = NULL;
7084 7085 7086 7087

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
7088
        return -1;
7089

7090 7091 7092 7093
    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    ret = snap == virDomainSnapshotGetCurrent(vm->snapshots);
7094

7095
 cleanup:
7096
    virDomainObjEndAPI(&vm);
7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110
    return ret;
}


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

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
7111
        return -1;
7112

C
Cole Robinson 已提交
7113
    if (!testSnapObjFromSnapshot(vm, snapshot))
7114 7115 7116 7117
        goto cleanup;

    ret = 1;

7118
 cleanup:
7119
    virDomainObjEndAPI(&vm);
7120 7121 7122
    return ret;
}

7123 7124 7125 7126 7127 7128
static int
testDomainSnapshotAlignDisks(virDomainObjPtr vm,
                             virDomainSnapshotDefPtr def,
                             unsigned int flags)
{
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
E
Eric Blake 已提交
7129
    bool align_match = true;
7130 7131 7132 7133 7134

    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) {
        align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
        align_match = false;
        if (virDomainObjIsActive(vm))
7135
            def->state = VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT;
7136
        else
7137
            def->state = VIR_DOMAIN_SNAPSHOT_SHUTOFF;
7138 7139 7140 7141 7142 7143 7144
        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);
7145
        def->memory = def->state == VIR_DOMAIN_SNAPSHOT_SHUTOFF ?
7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157
                      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)
{
7158
    testDriverPtr privconn = domain->conn->privateData;
7159
    virDomainObjPtr vm = NULL;
7160
    virDomainMomentObjPtr snap = NULL;
7161
    virDomainSnapshotPtr snapshot = NULL;
7162
    virObjectEventPtr event = NULL;
7163 7164
    bool update_current = true;
    bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
7165
    unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;
7166
    VIR_AUTOUNREF(virDomainSnapshotDefPtr) def = NULL;
7167 7168 7169 7170 7171 7172 7173

    /*
     * DISK_ONLY: Not implemented yet
     * REUSE_EXT: Not implemented yet
     *
     * NO_METADATA: Explicitly not implemented
     *
7174
     * REDEFINE + CURRENT: Implemented
7175 7176 7177 7178 7179 7180
     * HALT: Implemented
     * QUIESCE: Nothing to do
     * ATOMIC: Nothing to do
     * LIVE: Nothing to do
     */
    virCheckFlags(
7181 7182
        VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
        VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
7183 7184 7185
        VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
        VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
        VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
7186 7187
        VIR_DOMAIN_SNAPSHOT_CREATE_LIVE |
        VIR_DOMAIN_SNAPSHOT_CREATE_VALIDATE, NULL);
7188

7189 7190 7191 7192 7193
    if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)))
        update_current = false;
    if (redefine)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;

7194 7195 7196 7197 7198 7199 7200 7201 7202
    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;
    }

7203 7204 7205
    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_VALIDATE)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_VALIDATE;

7206 7207 7208
    if (!(def = virDomainSnapshotDefParseString(xmlDesc,
                                                privconn->caps,
                                                privconn->xmlopt,
7209
                                                NULL,
7210 7211 7212
                                                parse_flags)))
        goto cleanup;

7213
    if (redefine) {
C
Cole Robinson 已提交
7214
        if (virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
7215
                                          privconn->xmlopt,
C
Cole Robinson 已提交
7216
                                          &update_current, flags) < 0)
7217 7218
            goto cleanup;
    } else {
7219
        if (!(def->parent.dom = virDomainDefCopy(vm->def,
7220 7221 7222 7223
                                                 privconn->caps,
                                                 privconn->xmlopt,
                                                 NULL,
                                                 true)))
7224
            goto cleanup;
7225

7226
        if (testDomainSnapshotAlignDisks(vm, def, flags) < 0)
7227 7228 7229
            goto cleanup;
    }

7230 7231 7232 7233
    if (!snap) {
        if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
            goto cleanup;
        def = NULL;
7234 7235
    }

7236
    if (!redefine) {
7237
        if (VIR_STRDUP(snap->def->parent_name,
7238
                       virDomainSnapshotGetCurrentName(vm->snapshots)) < 0)
7239 7240 7241 7242 7243 7244
            goto cleanup;

        if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT) &&
            virDomainObjIsActive(vm)) {
            testDomainShutdownState(domain, vm,
                                    VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT);
7245
            event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
7246 7247 7248
                                    VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
        }
    }
7249

7250
    snapshot = virGetDomainSnapshot(domain, snap->def->name);
7251
 cleanup:
7252 7253
    if (vm) {
        if (snapshot) {
7254
            virDomainMomentObjPtr other;
7255
            if (update_current)
7256
                virDomainSnapshotSetCurrent(vm->snapshots, snap);
7257
            other = virDomainSnapshotFindByName(vm->snapshots,
7258
                                                snap->def->parent_name);
7259
            virDomainMomentSetParent(snap, other);
7260
        }
7261
        virDomainObjEndAPI(&vm);
7262
    }
7263
    virObjectEventStateQueue(privconn->eventState, event);
7264 7265 7266 7267
    return snapshot;
}


7268 7269 7270
typedef struct _testMomentRemoveData testMomentRemoveData;
typedef testMomentRemoveData *testMomentRemoveDataPtr;
struct _testMomentRemoveData {
7271 7272 7273 7274
    virDomainObjPtr vm;
    bool current;
};

7275
static int
7276
testDomainSnapshotDiscardAll(void *payload,
7277 7278
                             const void *name ATTRIBUTE_UNUSED,
                             void *data)
7279
{
7280
    virDomainMomentObjPtr snap = payload;
7281
    testMomentRemoveDataPtr curr = data;
7282

7283
    curr->current |= virDomainSnapshotObjListRemove(curr->vm->snapshots, snap);
7284
    return 0;
7285 7286
}

7287 7288 7289
typedef struct _testMomentReparentData testMomentReparentData;
typedef testMomentReparentData *testMomentReparentDataPtr;
struct _testMomentReparentData {
7290
    virDomainMomentObjPtr parent;
7291 7292 7293 7294
    virDomainObjPtr vm;
    int err;
};

7295
static int
7296 7297 7298
testDomainMomentReparentChildren(void *payload,
                                 const void *name ATTRIBUTE_UNUSED,
                                 void *data)
7299
{
7300 7301
    virDomainMomentObjPtr moment = payload;
    testMomentReparentDataPtr rep = data;
7302

7303
    if (rep->err < 0)
7304
        return 0;
7305

7306
    VIR_FREE(moment->def->parent_name);
7307 7308

    if (rep->parent->def &&
7309
        VIR_STRDUP(moment->def->parent_name, rep->parent->def->name) < 0) {
7310
        rep->err = -1;
7311
        return 0;
7312 7313
    }

7314
    return 0;
7315 7316 7317 7318 7319 7320 7321
}

static int
testDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
                         unsigned int flags)
{
    virDomainObjPtr vm = NULL;
7322 7323
    virDomainMomentObjPtr snap = NULL;
    virDomainMomentObjPtr parentsnap = NULL;
7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336
    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)) {
7337
        testMomentRemoveData rem;
7338 7339
        rem.vm = vm;
        rem.current = false;
7340 7341 7342
        virDomainMomentForEachDescendant(snap,
                                         testDomainSnapshotDiscardAll,
                                         &rem);
7343
        if (rem.current)
7344
            virDomainSnapshotSetCurrent(vm->snapshots, snap);
7345
    } else if (snap->nchildren) {
7346
        testMomentReparentData rep;
7347 7348 7349
        rep.parent = snap->parent;
        rep.vm = vm;
        rep.err = 0;
7350
        virDomainMomentForEachChild(snap,
7351
                                    testDomainMomentReparentChildren,
7352
                                    &rep);
7353 7354 7355
        if (rep.err < 0)
            goto cleanup;

7356
        virDomainMomentMoveChildren(snap, snap->parent);
7357 7358 7359
    }

    if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) {
7360
        virDomainMomentDropChildren(snap);
7361
    } else {
7362
        virDomainMomentDropParent(snap);
7363
        if (snap == virDomainSnapshotGetCurrent(vm->snapshots)) {
7364
            if (snap->def->parent_name) {
7365
                parentsnap = virDomainSnapshotFindByName(vm->snapshots,
7366
                                                         snap->def->parent_name);
7367
                if (!parentsnap)
7368
                    VIR_WARN("missing parent snapshot matching name '%s'",
7369
                             snap->def->parent_name);
7370
            }
7371
            virDomainSnapshotSetCurrent(vm->snapshots, parentsnap);
7372 7373 7374 7375 7376
        }
        virDomainSnapshotObjListRemove(vm->snapshots, snap);
    }

    ret = 0;
7377
 cleanup:
7378
    virDomainObjEndAPI(&vm);
7379 7380 7381 7382 7383 7384 7385
    return ret;
}

static int
testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                           unsigned int flags)
{
7386
    testDriverPtr privconn = snapshot->domain->conn->privateData;
7387
    virDomainObjPtr vm = NULL;
7388
    virDomainMomentObjPtr snap = NULL;
7389 7390
    virObjectEventPtr event = NULL;
    virObjectEventPtr event2 = NULL;
7391
    virDomainDefPtr config = NULL;
7392
    virDomainSnapshotDefPtr snapdef;
7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417
    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;
7418
    snapdef = virDomainSnapshotObjGetDef(snap);
7419 7420

    if (!vm->persistent &&
7421 7422
        snapdef->state != VIR_DOMAIN_SNAPSHOT_RUNNING &&
        snapdef->state != VIR_DOMAIN_SNAPSHOT_PAUSED &&
7423 7424 7425 7426 7427 7428 7429 7430 7431
        (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)) {
7432
        if (!snap->def->dom) {
7433 7434
            virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY,
                           _("snapshot '%s' lacks domain '%s' rollback info"),
7435
                           snap->def->name, vm->def->name);
7436 7437 7438
            goto cleanup;
        }
        if (virDomainObjIsActive(vm) &&
7439 7440
            !(snapdef->state == VIR_DOMAIN_SNAPSHOT_RUNNING ||
              snapdef->state == VIR_DOMAIN_SNAPSHOT_PAUSED) &&
7441 7442 7443 7444 7445 7446 7447 7448
            (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;
        }
    }

7449
    virDomainSnapshotSetCurrent(vm->snapshots, NULL);
7450

7451
    config = virDomainDefCopy(snap->def->dom, privconn->caps,
7452
                              privconn->xmlopt, NULL, true);
7453 7454 7455
    if (!config)
        goto cleanup;

7456 7457
    if (snapdef->state == VIR_DOMAIN_SNAPSHOT_RUNNING ||
        snapdef->state == VIR_DOMAIN_SNAPSHOT_PAUSED) {
7458 7459 7460 7461 7462 7463 7464
        /* 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.  */
7465 7466
            if (!virDomainDefCheckABIStability(vm->def, config,
                                               privconn->xmlopt)) {
7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479
                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);
7480
                event = virDomainEventLifecycleNewFromObj(vm,
7481 7482
                            VIR_DOMAIN_EVENT_STOPPED,
                            VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
7483
                virObjectEventStateQueue(privconn->eventState, event);
7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494
                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. */
7495
                event = virDomainEventLifecycleNewFromObj(vm,
7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508
                                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;
7509
            event = virDomainEventLifecycleNewFromObj(vm,
7510 7511 7512 7513 7514 7515
                                VIR_DOMAIN_EVENT_STARTED,
                                VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
        }

        /* Touch up domain state.  */
        if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING) &&
7516
            (snapdef->state == VIR_DOMAIN_SNAPSHOT_PAUSED ||
7517 7518 7519 7520 7521 7522
             (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 */
7523
                event2 = virDomainEventLifecycleNewFromObj(vm,
7524 7525 7526 7527 7528
                                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 已提交
7529
            virObjectUnref(event);
7530 7531 7532 7533
            event = NULL;

            if (was_stopped) {
                /* Transition 2 */
7534
                event = virDomainEventLifecycleNewFromObj(vm,
7535 7536 7537 7538
                                VIR_DOMAIN_EVENT_STARTED,
                                VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            } else if (was_running) {
                /* Transition 8 */
7539
                event = virDomainEventLifecycleNewFromObj(vm,
7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551
                                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);
7552
            event = virDomainEventLifecycleNewFromObj(vm,
7553 7554 7555 7556 7557 7558 7559 7560 7561
                                    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;

7562
            virObjectEventStateQueue(privconn->eventState, event);
7563
            event = virDomainEventLifecycleNewFromObj(vm,
7564 7565 7566
                            VIR_DOMAIN_EVENT_STARTED,
                            VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            if (paused) {
7567
                event2 = virDomainEventLifecycleNewFromObj(vm,
7568 7569 7570 7571 7572 7573
                                VIR_DOMAIN_EVENT_SUSPENDED,
                                VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
            }
        }
    }

7574
    virDomainSnapshotSetCurrent(vm->snapshots, snap);
7575
    ret = 0;
7576
 cleanup:
7577
    if (event) {
7578 7579
        virObjectEventStateQueue(privconn->eventState, event);
        virObjectEventStateQueue(privconn->eventState, event2);
C
Cole Robinson 已提交
7580
    } else {
C
Cédric Bosdonnat 已提交
7581
        virObjectUnref(event2);
7582
    }
7583
    virDomainObjEndAPI(&vm);
7584 7585 7586 7587 7588

    return ret;
}


7589
static virHypervisorDriver testHypervisorDriver = {
7590
    .name = "Test",
7591 7592 7593
    .connectOpen = testConnectOpen, /* 0.1.1 */
    .connectClose = testConnectClose, /* 0.1.1 */
    .connectGetVersion = testConnectGetVersion, /* 0.1.1 */
7594
    .connectGetHostname = testConnectGetHostname, /* 0.6.3 */
7595
    .connectGetMaxVcpus = testConnectGetMaxVcpus, /* 0.3.2 */
7596
    .nodeGetInfo = testNodeGetInfo, /* 0.1.1 */
7597
    .nodeGetCPUStats = testNodeGetCPUStats, /* 2.3.0 */
7598
    .nodeGetFreeMemory = testNodeGetFreeMemory, /* 2.3.0 */
7599
    .nodeGetFreePages = testNodeGetFreePages, /* 2.3.0 */
7600
    .connectGetCapabilities = testConnectGetCapabilities, /* 0.2.1 */
7601
    .connectGetSysinfo = testConnectGetSysinfo, /* 2.3.0 */
7602
    .connectGetType = testConnectGetType, /* 2.3.0 */
7603 7604 7605
    .connectListDomains = testConnectListDomains, /* 0.1.1 */
    .connectNumOfDomains = testConnectNumOfDomains, /* 0.1.1 */
    .connectListAllDomains = testConnectListAllDomains, /* 0.9.13 */
7606
    .domainCreateXML = testDomainCreateXML, /* 0.1.4 */
7607 7608 7609 7610 7611 7612 7613 7614 7615
    .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 */
7616
    .domainDestroyFlags = testDomainDestroyFlags, /* 4.2.0 */
7617
    .domainGetOSType = testDomainGetOSType, /* 0.1.9 */
7618
    .domainGetLaunchSecurityInfo = testDomainGetLaunchSecurityInfo, /* 5.5.0 */
7619 7620 7621
    .domainGetMaxMemory = testDomainGetMaxMemory, /* 0.1.4 */
    .domainSetMaxMemory = testDomainSetMaxMemory, /* 0.1.1 */
    .domainSetMemory = testDomainSetMemory, /* 0.1.4 */
E
Eric Blake 已提交
7622
    .domainSetMemoryFlags = testDomainSetMemoryFlags, /* 5.6.0 */
7623
    .domainGetHostname = testDomainGetHostname, /* 5.5.0 */
7624
    .domainGetInfo = testDomainGetInfo, /* 0.1.1 */
7625
    .domainGetState = testDomainGetState, /* 0.9.2 */
7626
    .domainGetTime = testDomainGetTime, /* 5.4.0 */
7627
    .domainSave = testDomainSave, /* 0.3.2 */
7628
    .domainSaveFlags = testDomainSaveFlags, /* 0.9.4 */
7629
    .domainRestore = testDomainRestore, /* 0.3.2 */
7630
    .domainRestoreFlags = testDomainRestoreFlags, /* 0.9.4 */
7631
    .domainSaveImageDefineXML = testDomainSaveImageDefineXML, /* 5.5.0 */
7632
    .domainSaveImageGetXMLDesc = testDomainSaveImageGetXMLDesc, /* 5.5.0 */
7633
    .domainCoreDump = testDomainCoreDump, /* 0.3.2 */
7634
    .domainCoreDumpWithFormat = testDomainCoreDumpWithFormat, /* 1.2.3 */
7635
    .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */
7636 7637 7638
    .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */
    .domainGetVcpusFlags = testDomainGetVcpusFlags, /* 0.8.5 */
    .domainPinVcpu = testDomainPinVcpu, /* 0.7.3 */
E
Eric Blake 已提交
7639
    .domainPinVcpuFlags = testDomainPinVcpuFlags, /* 5.6.0 */
7640
    .domainGetVcpus = testDomainGetVcpus, /* 0.7.3 */
7641
    .domainGetVcpuPinInfo = testDomainGetVcpuPinInfo, /* 1.2.18 */
7642 7643
    .domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
    .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
7644
    .domainGetMemoryParameters = testDomainGetMemoryParameters, /* 5.6.0 */
7645
    .domainGetNumaParameters = testDomainGetNumaParameters, /* 5.6.0 */
7646
    .domainGetInterfaceParameters = testDomainGetInterfaceParameters, /* 5.6.0 */
7647 7648
    .connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
    .connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
7649 7650 7651
    .domainCreate = testDomainCreate, /* 0.1.11 */
    .domainCreateWithFlags = testDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = testDomainDefineXML, /* 0.1.11 */
7652
    .domainDefineXMLFlags = testDomainDefineXMLFlags, /* 1.2.12 */
7653
    .domainUndefine = testDomainUndefine, /* 0.1.11 */
7654
    .domainUndefineFlags = testDomainUndefineFlags, /* 0.9.4 */
7655 7656
    .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
    .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
7657
    .domainGetDiskErrors = testDomainGetDiskErrors, /* 5.4.0 */
7658
    .domainGetFSInfo = testDomainGetFSInfo, /* 5.6.0 */
7659
    .domainSetPerfEvents = testDomainSetPerfEvents, /* 5.6.0 */
7660
    .domainGetPerfEvents = testDomainGetPerfEvents, /* 5.6.0 */
7661
    .domainGetSchedulerType = testDomainGetSchedulerType, /* 0.3.2 */
7662 7663 7664 7665
    .domainGetSchedulerParameters = testDomainGetSchedulerParameters, /* 0.3.2 */
    .domainGetSchedulerParametersFlags = testDomainGetSchedulerParametersFlags, /* 0.9.2 */
    .domainSetSchedulerParameters = testDomainSetSchedulerParameters, /* 0.3.2 */
    .domainSetSchedulerParametersFlags = testDomainSetSchedulerParametersFlags, /* 0.9.2 */
7666
    .domainBlockStats = testDomainBlockStats, /* 0.7.0 */
7667
    .domainInterfaceAddresses = testDomainInterfaceAddresses, /* 5.4.0 */
7668 7669
    .domainInterfaceStats = testDomainInterfaceStats, /* 0.7.0 */
    .nodeGetCellsFreeMemory = testNodeGetCellsFreeMemory, /* 0.4.2 */
7670 7671 7672 7673
    .connectDomainEventRegister = testConnectDomainEventRegister, /* 0.6.0 */
    .connectDomainEventDeregister = testConnectDomainEventDeregister, /* 0.6.0 */
    .connectIsEncrypted = testConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = testConnectIsSecure, /* 0.7.3 */
7674 7675 7676
    .domainIsActive = testDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = testDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = testDomainIsUpdated, /* 0.8.6 */
7677 7678 7679
    .connectDomainEventRegisterAny = testConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = testConnectDomainEventDeregisterAny, /* 0.8.0 */
    .connectIsAlive = testConnectIsAlive, /* 0.9.8 */
7680
    .nodeGetCPUMap = testNodeGetCPUMap, /* 1.0.0 */
7681
    .domainRename = testDomainRename, /* 4.1.0 */
7682
    .domainScreenshot = testDomainScreenshot, /* 1.0.5 */
7683
    .domainSendKey = testDomainSendKey, /* 5.5.0 */
7684 7685
    .domainGetMetadata = testDomainGetMetadata, /* 1.1.3 */
    .domainSetMetadata = testDomainSetMetadata, /* 1.1.3 */
7686
    .domainSendProcessSignal = testDomainSendProcessSignal, /* 5.5.0 */
7687
    .connectGetCPUModelNames = testConnectGetCPUModelNames, /* 1.1.3 */
7688 7689 7690
    .domainManagedSave = testDomainManagedSave, /* 1.1.4 */
    .domainHasManagedSaveImage = testDomainHasManagedSaveImage, /* 1.1.4 */
    .domainManagedSaveRemove = testDomainManagedSaveRemove, /* 1.1.4 */
7691
    .domainMemoryPeek = testDomainMemoryPeek, /* 5.4.0 */
7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705

    .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 */
7706 7707 7708
    .domainSnapshotCreateXML = testDomainSnapshotCreateXML, /* 1.1.4 */
    .domainRevertToSnapshot = testDomainRevertToSnapshot, /* 1.1.4 */
    .domainSnapshotDelete = testDomainSnapshotDelete, /* 1.1.4 */
7709

E
Eric Blake 已提交
7710
    .connectBaselineCPU = testConnectBaselineCPU, /* 1.2.0 */
7711 7712 7713
};

static virNetworkDriver testNetworkDriver = {
7714 7715 7716 7717 7718
    .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 */
7719 7720
    .connectNetworkEventRegisterAny = testConnectNetworkEventRegisterAny, /* 1.2.1 */
    .connectNetworkEventDeregisterAny = testConnectNetworkEventDeregisterAny, /* 1.2.1 */
7721 7722 7723 7724
    .networkLookupByUUID = testNetworkLookupByUUID, /* 0.3.2 */
    .networkLookupByName = testNetworkLookupByName, /* 0.3.2 */
    .networkCreateXML = testNetworkCreateXML, /* 0.3.2 */
    .networkDefineXML = testNetworkDefineXML, /* 0.3.2 */
7725
    .networkUndefine = testNetworkUndefine, /* 0.3.2 */
7726
    .networkUpdate = testNetworkUpdate, /* 0.10.2 */
7727
    .networkCreate = testNetworkCreate, /* 0.3.2 */
7728 7729 7730 7731 7732 7733 7734
    .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 */
7735 7736
};

L
Laine Stump 已提交
7737
static virInterfaceDriver testInterfaceDriver = {
7738 7739 7740 7741
    .connectNumOfInterfaces = testConnectNumOfInterfaces, /* 0.7.0 */
    .connectListInterfaces = testConnectListInterfaces, /* 0.7.0 */
    .connectNumOfDefinedInterfaces = testConnectNumOfDefinedInterfaces, /* 0.7.0 */
    .connectListDefinedInterfaces = testConnectListDefinedInterfaces, /* 0.7.0 */
7742
    .connectListAllInterfaces = testConnectListAllInterfaces, /* 4.6.0 */
7743 7744
    .interfaceLookupByName = testInterfaceLookupByName, /* 0.7.0 */
    .interfaceLookupByMACString = testInterfaceLookupByMACString, /* 0.7.0 */
7745 7746 7747 7748 7749 7750
    .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 */
7751 7752 7753
    .interfaceChangeBegin = testInterfaceChangeBegin,   /* 0.9.2 */
    .interfaceChangeCommit = testInterfaceChangeCommit,  /* 0.9.2 */
    .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */
L
Laine Stump 已提交
7754 7755 7756
};


7757
static virStorageDriver testStorageDriver = {
7758 7759 7760 7761 7762 7763
    .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 */
7764 7765
    .connectStoragePoolEventRegisterAny = testConnectStoragePoolEventRegisterAny, /* 2.0.0 */
    .connectStoragePoolEventDeregisterAny = testConnectStoragePoolEventDeregisterAny, /* 2.0.0 */
7766 7767 7768
    .storagePoolLookupByName = testStoragePoolLookupByName, /* 0.5.0 */
    .storagePoolLookupByUUID = testStoragePoolLookupByUUID, /* 0.5.0 */
    .storagePoolLookupByVolume = testStoragePoolLookupByVolume, /* 0.5.0 */
7769 7770
    .storagePoolCreateXML = testStoragePoolCreateXML, /* 0.5.0 */
    .storagePoolDefineXML = testStoragePoolDefineXML, /* 0.5.0 */
7771 7772
    .storagePoolBuild = testStoragePoolBuild, /* 0.5.0 */
    .storagePoolUndefine = testStoragePoolUndefine, /* 0.5.0 */
7773
    .storagePoolCreate = testStoragePoolCreate, /* 0.5.0 */
7774 7775 7776 7777 7778 7779 7780
    .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 */
7781
    .storagePoolNumOfVolumes = testStoragePoolNumOfVolumes, /* 0.5.0 */
7782 7783 7784
    .storagePoolListVolumes = testStoragePoolListVolumes, /* 0.5.0 */
    .storagePoolListAllVolumes = testStoragePoolListAllVolumes, /* 0.10.2 */

7785 7786 7787 7788 7789 7790 7791 7792 7793
    .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 */
7794 7795
    .storagePoolIsActive = testStoragePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = testStoragePoolIsPersistent, /* 0.7.3 */
7796 7797
};

7798
static virNodeDeviceDriver testNodeDeviceDriver = {
7799
    .connectListAllNodeDevices = testConnectListAllNodeDevices, /* 4.1.0 */
7800 7801
    .connectNodeDeviceEventRegisterAny = testConnectNodeDeviceEventRegisterAny, /* 2.2.0 */
    .connectNodeDeviceEventDeregisterAny = testConnectNodeDeviceEventDeregisterAny, /* 2.2.0 */
7802 7803 7804 7805 7806 7807 7808 7809 7810
    .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 */
7811 7812
};

7813
static virConnectDriver testConnectDriver = {
7814
    .localOnly = true,
7815
    .uriSchemes = (const char *[]){ "test", NULL },
7816 7817 7818 7819 7820 7821 7822
    .hypervisorDriver = &testHypervisorDriver,
    .interfaceDriver = &testInterfaceDriver,
    .networkDriver = &testNetworkDriver,
    .nodeDeviceDriver = &testNodeDeviceDriver,
    .nwfilterDriver = NULL,
    .secretDriver = NULL,
    .storageDriver = &testStorageDriver,
7823 7824
};

7825 7826 7827 7828 7829 7830 7831 7832
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
7833 7834
    return virRegisterConnectDriver(&testConnectDriver,
                                    false);
7835
}