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

30

31
#include "virerror.h"
32
#include "datatypes.h"
33
#include "test_driver.h"
34
#include "virbuffer.h"
35
#include "viruuid.h"
36
#include "capabilities.h"
37
#include "configmake.h"
38
#include "viralloc.h"
J
John Ferlan 已提交
39
#include "virnetworkobj.h"
L
Laine Stump 已提交
40
#include "interface_conf.h"
41
#include "checkpoint_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 "virdomainobjlist.h"
J
John Ferlan 已提交
63
#include "virinterfaceobj.h"
64
#include "virhostcpu.h"
65
#include "virdomaincheckpointobjlist.h"
66
#include "virdomainsnapshotobjlist.h"
67
#include "virkeycode.h"
J
Ján Tomko 已提交
68
#include "virutil.h"
69

70 71
#define VIR_FROM_THIS VIR_FROM_TEST

72 73
VIR_LOG_INIT("test.test_driver");

74

75 76 77 78
#define MAX_CPUS 128

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

#define MAX_CELLS 128
87

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

95
struct _testDriver {
96
    virObjectLockable parent;
97

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

109
    /* g_atomic access only */
110 111
    volatile int nextDomID;

112 113 114 115 116 117 118 119 120 121
    /* 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;
122
    virObjectEventStatePtr eventState;
123
};
124 125
typedef struct _testDriver testDriver;
typedef testDriver *testDriverPtr;
126

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

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

    return 0;
}
139
VIR_ONCE_GLOBAL_INIT(testDriver);
140

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

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

155
static void
156
testDriverDispose(void *obj)
157
{
158
    testDriverPtr driver = obj;
159
    size_t i;
160 161 162 163

    virObjectUnref(driver->caps);
    virObjectUnref(driver->xmlopt);
    virObjectUnref(driver->domains);
164
    virNodeDeviceObjListFree(driver->devs);
165
    virObjectUnref(driver->networks);
166
    virObjectUnref(driver->ifaces);
167
    virObjectUnref(driver->pools);
168
    virObjectUnref(driver->eventState);
169 170 171 172 173
    for (i = 0; i < driver->numAuths; i++) {
        g_free(driver->auths[i].username);
        g_free(driver->auths[i].password);
    }
    g_free(driver->auths);
174 175
}

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

    unsigned int num_snap_nodes;
    xmlNodePtr *snap_nodes;
185 186 187 188 189 190
};

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

static int
204
testDomainDefNamespaceParse(xmlXPathContextPtr ctxt,
205 206 207
                            void **data)
{
    testDomainNamespaceDefPtr nsdata = NULL;
208 209
    int tmp, n;
    size_t i;
210
    unsigned int tmpuint;
211
    g_autofree xmlNodePtr *nodes = NULL;
212 213 214 215

    if (VIR_ALLOC(nsdata) < 0)
        return -1;

216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
    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++;
    }

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

248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
    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;
    }

264 265 266 267 268
    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 已提交
269 270 271 272 273
    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;
    }
274

275 276 277
    *data = nsdata;
    return 0;

278
 error:
279 280 281
    testDomainDefNamespaceFree(nsdata);
    return -1;
}
282

283
static virCapsPtr
284 285
testBuildCapabilities(virConnectPtr conn)
{
286
    testDriverPtr privconn = conn->privateData;
287 288
    virCapsPtr caps;
    virCapsGuestPtr guest;
289 290
    int guest_types[] = { VIR_DOMAIN_OSTYPE_HVM,
                          VIR_DOMAIN_OSTYPE_XEN };
291
    size_t i, j;
292

293
    if ((caps = virCapabilitiesNew(VIR_ARCH_I686, false, false)) == NULL)
294
        goto error;
295

296
    if (virCapabilitiesAddHostFeature(caps, "pae") < 0)
297
        goto error;
298
    if (virCapabilitiesAddHostFeature(caps, "nonpae") < 0)
299
        goto error;
300

301 302
    virCapabilitiesHostInitIOMMU(caps);

303
    if (VIR_ALLOC_N(caps->host.pagesSize, 4) < 0)
304 305 306
        goto error;

    caps->host.pagesSize[caps->host.nPagesSize++] = 4;
307
    caps->host.pagesSize[caps->host.nPagesSize++] = 8;
308
    caps->host.pagesSize[caps->host.nPagesSize++] = 2048;
309
    caps->host.pagesSize[caps->host.nPagesSize++] = 1024 * 1024;
310

311
    caps->host.numa = virCapabilitiesHostNUMANew();
312
    for (i = 0; i < privconn->numCells; i++) {
313
        virCapsHostNUMACellCPUPtr cpu_cells;
314
        virCapsHostNUMACellPageInfoPtr pages;
315
        size_t nPages = caps->host.nPagesSize - 1;
316

317
        if (VIR_ALLOC_N(cpu_cells, privconn->cells[i].numCpus) < 0 ||
318
            VIR_ALLOC_N(pages, nPages) < 0) {
319 320 321 322
                VIR_FREE(cpu_cells);
                goto error;
            }

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

326 327 328 329 330 331 332
        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];
333 334

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

336 337 338 339
        virCapabilitiesHostNUMAAddCell(caps->host.numa,
                                       i, privconn->cells[i].mem,
                                       privconn->cells[i].numCpus,
                                       cpu_cells, 0, NULL, nPages, pages);
340 341
    }

342
    for (i = 0; i < G_N_ELEMENTS(guest_types); i++) {
343 344
        if ((guest = virCapabilitiesAddGuest(caps,
                                             guest_types[i],
345
                                             VIR_ARCH_I686,
346 347 348 349
                                             TEST_EMULATOR,
                                             NULL,
                                             0,
                                             NULL)) == NULL)
350
            goto error;
351

352
        if (virCapabilitiesAddGuestDomain(guest,
353
                                          VIR_DOMAIN_VIRT_TEST,
354 355 356 357
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
358
            goto error;
359

360 361
        virCapabilitiesAddGuestFeature(guest, VIR_CAPS_GUEST_FEATURE_TYPE_PAE);
        virCapabilitiesAddGuestFeature(guest, VIR_CAPS_GUEST_FEATURE_TYPE_NONPAE);
362 363
    }

364 365
    caps->host.nsecModels = 1;
    if (VIR_ALLOC_N(caps->host.secModels, caps->host.nsecModels) < 0)
366
        goto error;
367
    caps->host.secModels[0].model = g_strdup("testSecurity");
368

369
    caps->host.secModels[0].doi = g_strdup("");
370

371
    return caps;
372

373
 error:
374
    virObjectUnref(caps);
375
    return NULL;
376 377
}

378

379 380 381 382
typedef struct _testDomainObjPrivate testDomainObjPrivate;
typedef testDomainObjPrivate *testDomainObjPrivatePtr;
struct _testDomainObjPrivate {
    testDriverPtr driver;
383 384

    bool frozen[2]; /* used by file system related calls */
385 386 387 388

    /* used by get/set time APIs */
    long long seconds;
    unsigned int nseconds;
389 390 391 392 393 394 395 396 397 398 399 400
};


static void *
testDomainObjPrivateAlloc(void *opaque)
{
    testDomainObjPrivatePtr priv;

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

    priv->driver = opaque;
401
    priv->frozen[0] = priv->frozen[1] = false;
402

403 404 405
    priv->seconds = 627319920;
    priv->nseconds = 0;

406 407 408 409
    return priv;
}


410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
static int
testDomainDevicesDefPostParse(virDomainDeviceDefPtr dev G_GNUC_UNUSED,
                              const virDomainDef *def G_GNUC_UNUSED,
                              unsigned int parseFlags G_GNUC_UNUSED,
                              void *opaque G_GNUC_UNUSED,
                              void *parseOpaque G_GNUC_UNUSED)
{
    if (dev->type == VIR_DOMAIN_DEVICE_VIDEO &&
        dev->data.video->type == VIR_DOMAIN_VIDEO_TYPE_DEFAULT) {
        if (def->os.type == VIR_DOMAIN_OSTYPE_XEN ||
            def->os.type == VIR_DOMAIN_OSTYPE_LINUX)
            dev->data.video->type = VIR_DOMAIN_VIDEO_TYPE_XEN;
        else if (ARCH_IS_PPC64(def->os.arch))
            dev->data.video->type = VIR_DOMAIN_VIDEO_TYPE_VGA;
        else
            dev->data.video->type = VIR_DOMAIN_VIDEO_TYPE_CIRRUS;
    }

    return 0;
}


432 433 434 435 436 437 438 439
static void
testDomainObjPrivateFree(void *data)
{
    testDomainObjPrivatePtr priv = data;
    VIR_FREE(priv);
}


440 441 442
static testDriverPtr
testDriverNew(void)
{
443
    virXMLNamespace ns = {
444 445
        .parse = testDomainDefNamespaceParse,
        .free = testDomainDefNamespaceFree,
446
        .prefix = "test",
447
        .uri = "http://libvirt.org/schemas/domain/test/1.0",
448
    };
449 450 451 452 453 454 455
    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,
456
        .devicesPostParseCallback = testDomainDevicesDefPostParse,
457
        .defArch = VIR_ARCH_I686,
458
    };
459 460 461 462
    virDomainXMLPrivateDataCallbacks privatecb = {
        .alloc = testDomainObjPrivateAlloc,
        .free = testDomainObjPrivateFree,
    };
463 464
    testDriverPtr ret;

465
    if (testDriverInitialize() < 0)
466 467
        return NULL;

468 469
    if (!(ret = virObjectLockableNew(testDriverClass)))
        return NULL;
470

471
    if (!(ret->xmlopt = virDomainXMLOptionNew(&config, &privatecb, &ns, NULL, NULL)) ||
472
        !(ret->eventState = virObjectEventStateNew()) ||
473
        !(ret->ifaces = virInterfaceObjListNew()) ||
474
        !(ret->domains = virDomainObjListNew()) ||
475
        !(ret->networks = virNetworkObjListNew()) ||
476 477
        !(ret->devs = virNodeDeviceObjListNew()) ||
        !(ret->pools = virStoragePoolObjListNew()))
478 479
        goto error;

480
    g_atomic_int_set(&ret->nextDomID, 1);
481 482 483 484

    return ret;

 error:
485
    virObjectUnref(ret);
486 487 488 489
    return NULL;
}


490 491
static const char *defaultConnXML =
"<node>"
492 493
"<domain type='test'>"
"  <name>test</name>"
494
"  <uuid>6695eb01-f6a4-8304-79aa-97f2502e193f</uuid>"
495 496 497 498 499 500
"  <memory>8388608</memory>"
"  <currentMemory>2097152</currentMemory>"
"  <vcpu>2</vcpu>"
"  <os>"
"    <type>hvm</type>"
"  </os>"
501
"  <devices>"
502 503 504 505 506
"    <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>"
507 508 509 510 511
"    <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>"
512 513 514
"    <memballoon model='virtio'>"
"      <address type='pci' domain='0x0000' bus='0x00' slot='0x2' function='0x0'/>"
"    </memballoon>"
515
"  </devices>"
516 517
"</domain>"
""
518 519
"<network>"
"  <name>default</name>"
520
"  <uuid>dd8fe884-6c02-601e-7551-cca97df1c5df</uuid>"
521
"  <bridge name='virbr0'/>"
522 523 524
"  <forward/>"
"  <ip address='192.168.122.1' netmask='255.255.255.0'>"
"    <dhcp>"
525
"      <range start='192.168.122.2' end='192.168.122.254'/>"
526 527
"    </dhcp>"
"  </ip>"
528 529
"</network>"
""
L
Laine Stump 已提交
530 531 532 533 534 535 536 537
"<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>"
538 539
"</interface>"
""
C
Cole Robinson 已提交
540 541
"<pool type='dir'>"
"  <name>default-pool</name>"
542
"  <uuid>dfe224cb-28fb-8dd0-c4b2-64eb3f0f4566</uuid>"
C
Cole Robinson 已提交
543 544 545
"  <target>"
"    <path>/default-pool</path>"
"  </target>"
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
"</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>"
564
"<device>"
565
"  <name>scsi_host1</name>"
566 567 568
"  <parent>computer</parent>"
"  <capability type='scsi_host'>"
"    <host>1</host>"
569
"    <unique_id>0</unique_id>"
570 571 572
"    <capability type='fc_host'>"
"      <wwnn>2000000012341234</wwnn>"
"      <wwpn>1000000012341234</wwpn>"
573 574 575 576
"      <fabric_wwn>2000000043214321</fabric_wwn>"
"    </capability>"
"    <capability type='vport_ops'>"
"      <max_vports>127</max_vports>"
577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
"      <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>"
594
"      <vports>0</vports>"
595 596 597
"    </capability>"
"  </capability>"
"</device>"
598 599 600 601 602 603 604 605 606 607 608 609 610
"<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>"
611 612
"</node>";

C
Cole Robinson 已提交
613

614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
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";

637
static const unsigned long long defaultPoolCap = (100 * 1024 * 1024 * 1024ull);
638
static const unsigned long long defaultPoolAlloc;
C
Cole Robinson 已提交
639

640
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr obj);
641
static int testNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
642
static virNetworkObjPtr testNetworkObjFindByName(testDriverPtr privconn, const char *name);
643

644 645 646 647
static virDomainObjPtr
testDomObjFromDomain(virDomainPtr domain)
{
    virDomainObjPtr vm;
648
    testDriverPtr driver = domain->conn->privateData;
649 650
    char uuidstr[VIR_UUID_STRING_BUFLEN];

651
    vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
652 653 654 655 656 657 658 659 660 661
    if (!vm) {
        virUUIDFormat(domain->uuid, uuidstr);
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching uuid '%s' (%s)"),
                       uuidstr, domain->name);
    }

    return vm;
}

662
static char *
663 664
testDomainGenerateIfname(virDomainDefPtr domdef)
{
665
    int maxif = 1024;
666
    int ifctr;
667 668

    for (ifctr = 0; ifctr < maxif; ++ifctr) {
M
Michal Privoznik 已提交
669
        virDomainNetDefPtr net = NULL;
670 671
        char *ifname;

672
        ifname = g_strdup_printf("testnet%d", ifctr);
673 674

        /* Generate network interface names */
M
Michal Privoznik 已提交
675
        if (!(net = virDomainNetFindByName(domdef, ifname)))
676
            return ifname;
677
        VIR_FREE(ifname);
678 679
    }

680 681
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Exceeded max iface limit %d"), maxif);
682 683 684
    return NULL;
}

685
static int
686
testDomainGenerateIfnames(virDomainDefPtr domdef)
687
{
688
    size_t i = 0;
689 690 691 692 693 694

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

695
        ifname = testDomainGenerateIfname(domdef);
696
        if (!ifname)
697
            return -1;
698 699 700 701

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

702
    return 0;
703 704
}

705

706 707
static void
testDomainShutdownState(virDomainPtr domain,
J
Jiri Denemark 已提交
708 709
                        virDomainObjPtr privdom,
                        virDomainShutoffReason reason)
710
{
711
    virDomainObjRemoveTransientDef(privdom);
J
Jiri Denemark 已提交
712
    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF, reason);
713

714 715 716 717
    if (domain)
        domain->id = -1;
}

718
/* Set up domain runtime state */
719
static int
720
testDomainStartState(testDriverPtr privconn,
J
Jiri Denemark 已提交
721 722
                     virDomainObjPtr dom,
                     virDomainRunningReason reason)
723
{
724
    int ret = -1;
725

J
Jiri Denemark 已提交
726
    virDomainObjSetState(dom, VIR_DOMAIN_RUNNING, reason);
727
    dom->def->id = g_atomic_int_add(&privconn->nextDomID, 1);
728

729
    if (virDomainObjSetDefTransient(privconn->xmlopt,
730
                                    dom, NULL) < 0) {
731 732 733
        goto cleanup;
    }

C
Cole Robinson 已提交
734
    dom->hasManagedSave = false;
735
    ret = 0;
736
 cleanup:
737
    if (ret < 0)
J
Jiri Denemark 已提交
738
        testDomainShutdownState(NULL, dom, VIR_DOMAIN_SHUTOFF_FAILED);
739
    return ret;
740
}
741

742

743
static char *testBuildFilename(const char *relativeTo,
744 745
                               const char *filename)
{
746 747
    char *offset;
    int baseLen;
748 749
    char *ret;

750
    if (!filename || filename[0] == '\0')
751
        return NULL;
752
    if (filename[0] == '/') {
753
        ret = g_strdup(filename);
754 755
        return ret;
    }
756

757
    offset = strrchr(relativeTo, '/');
758
    if ((baseLen = (offset-relativeTo+1))) {
759
        char *absFile;
C
Chris Lalancette 已提交
760 761
        int totalLen = baseLen + strlen(filename) + 1;
        if (VIR_ALLOC_N(absFile, totalLen) < 0)
762
            return NULL;
763
        if (virStrncpy(absFile, relativeTo, baseLen, totalLen) < 0) {
C
Chris Lalancette 已提交
764 765 766
            VIR_FREE(absFile);
            return NULL;
        }
767 768 769
        strcat(absFile, filename);
        return absFile;
    } else {
770
        ret = g_strdup(filename);
771
        return ret;
772
    }
773 774
}

C
Cole Robinson 已提交
775 776 777 778 779 780
static xmlNodePtr
testParseXMLDocFromFile(xmlNodePtr node, const char *file, const char *type)
{
    xmlNodePtr ret = NULL;
    xmlDocPtr doc = NULL;
    char *absFile = NULL;
781
    g_autofree char *relFile = NULL;
C
Cole Robinson 已提交
782

783
    if ((relFile = virXMLPropString(node, "file"))) {
C
Cole Robinson 已提交
784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804
        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;
    }

805
 error:
C
Cole Robinson 已提交
806 807 808 809
    xmlFreeDoc(doc);
    return ret;
}

810 811 812 813 814
static int
testParseNodeInfo(virNodeInfoPtr nodeInfo, xmlXPathContextPtr ctxt)
{
    long l;
    int ret;
815
    g_autofree char *str = NULL;
816

817
    ret = virXPathLong("string(/node/cpu/nodes[1])", ctxt, &l);
818 819 820
    if (ret == 0) {
        nodeInfo->nodes = l;
    } else if (ret == -2) {
821 822
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu nodes value"));
823
        return -1;
824
    }
825

826
    ret = virXPathLong("string(/node/cpu/sockets[1])", ctxt, &l);
827 828 829
    if (ret == 0) {
        nodeInfo->sockets = l;
    } else if (ret == -2) {
830 831
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu sockets value"));
832
        return -1;
833
    }
834

835
    ret = virXPathLong("string(/node/cpu/cores[1])", ctxt, &l);
836 837 838
    if (ret == 0) {
        nodeInfo->cores = l;
    } else if (ret == -2) {
839 840
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu cores value"));
841
        return -1;
842 843
    }

844
    ret = virXPathLong("string(/node/cpu/threads[1])", ctxt, &l);
845 846 847
    if (ret == 0) {
        nodeInfo->threads = l;
    } else if (ret == -2) {
848 849
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu threads value"));
850
        return -1;
851
    }
852

853 854
    nodeInfo->cpus = (nodeInfo->cores * nodeInfo->threads *
                      nodeInfo->sockets * nodeInfo->nodes);
855
    ret = virXPathLong("string(/node/cpu/active[1])", ctxt, &l);
856
    if (ret == 0) {
857
        if (l < nodeInfo->cpus)
858
            nodeInfo->cpus = l;
859
    } else if (ret == -2) {
860 861
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu active value"));
862
        return -1;
863
    }
864
    ret = virXPathLong("string(/node/cpu/mhz[1])", ctxt, &l);
865 866 867
    if (ret == 0) {
        nodeInfo->mhz = l;
    } else if (ret == -2) {
868 869
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node cpu mhz value"));
870
        return -1;
871 872
    }

873
    str = virXPathString("string(/node/cpu/model[1])", ctxt);
874
    if (str != NULL) {
875
        if (virStrcpyStatic(nodeInfo->model, str) < 0) {
876 877
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Model %s too big for destination"), str);
878
            return -1;
C
Chris Lalancette 已提交
879
        }
880 881
    }

882
    ret = virXPathLong("string(/node/memory[1])", ctxt, &l);
883 884 885
    if (ret == 0) {
        nodeInfo->memory = l;
    } else if (ret == -2) {
886 887
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid node memory value"));
888
        return -1;
889
    }
890

891 892 893
    return 0;
}

894
static int
895
testParseDomainSnapshots(testDriverPtr privconn,
896 897 898 899 900 901 902
                         virDomainObjPtr domobj,
                         const char *file,
                         xmlXPathContextPtr ctxt)
{
    size_t i;
    testDomainNamespaceDefPtr nsdata = domobj->def->namespaceData;
    xmlNodePtr *nodes = nsdata->snap_nodes;
903
    bool cur;
904 905

    for (i = 0; i < nsdata->num_snap_nodes; i++) {
906
        virDomainMomentObjPtr snap;
907 908 909 910
        virDomainSnapshotDefPtr def;
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                  "domainsnapshot");
        if (!node)
911
            return -1;
912 913 914

        def = virDomainSnapshotDefParseNode(ctxt->doc, node,
                                            privconn->xmlopt,
915
                                            NULL,
916
                                            &cur,
917 918 919 920
                                            VIR_DOMAIN_SNAPSHOT_PARSE_DISKS |
                                            VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL |
                                            VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE);
        if (!def)
921
            return -1;
922 923

        if (!(snap = virDomainSnapshotAssignDef(domobj->snapshots, def))) {
924
            virObjectUnref(def);
925
            return -1;
926 927
        }

928
        if (cur) {
929
            if (virDomainSnapshotGetCurrent(domobj->snapshots)) {
930 931
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("more than one snapshot claims to be active"));
932
                return -1;
933 934
            }

935
            virDomainSnapshotSetCurrent(domobj->snapshots, snap);
936 937 938 939 940 941 942
        }
    }

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

946
    return 0;
947 948
}

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

    num = virXPathNodeSet("/node/domain", ctxt, &nodes);
960
    if (num < 0)
961
        return -1;
962

963
    for (i = 0; i < num; i++) {
964
        virDomainDefPtr def;
965
        testDomainNamespaceDefPtr nsdata;
C
Cole Robinson 已提交
966 967 968 969 970
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file, "domain");
        if (!node)
            goto error;

        def = virDomainDefParseNode(ctxt->doc, node,
971
                                    privconn->xmlopt, NULL,
972
                                    VIR_DOMAIN_DEF_PARSE_INACTIVE);
C
Cole Robinson 已提交
973 974
        if (!def)
            goto error;
975

976
        if (testDomainGenerateIfnames(def) < 0 ||
977
            !(obj = virDomainObjListAdd(privconn->domains,
978
                                        def,
979
                                        privconn->xmlopt,
980
                                        0, NULL))) {
981
            virDomainDefFree(def);
982 983
            goto error;
        }
984

985
        if (testParseDomainSnapshots(privconn, obj, file, ctxt) < 0)
986 987
            goto error;

988
        nsdata = def->namespaceData;
989
        obj->persistent = !nsdata->transient;
C
Cole Robinson 已提交
990
        obj->hasManagedSave = nsdata->hasManagedSave;
991 992 993

        if (nsdata->runstate != VIR_DOMAIN_SHUTOFF) {
            if (testDomainStartState(privconn, obj,
994
                                     VIR_DOMAIN_RUNNING_BOOTED) < 0)
995 996 997
                goto error;
        } else {
            testDomainShutdownState(NULL, obj, 0);
998
        }
999
        virDomainObjSetState(obj, nsdata->runstate, 0);
1000

1001
        virDomainObjEndAPI(&obj);
1002
    }
1003

1004
    ret = 0;
1005
 error:
1006
    virDomainObjEndAPI(&obj);
1007 1008 1009
    return ret;
}

1010

1011
static int
1012
testParseNetworks(testDriverPtr privconn,
C
Cole Robinson 已提交
1013 1014
                  const char *file,
                  xmlXPathContextPtr ctxt)
1015
{
1016
    int num;
1017 1018
    size_t i;
    virNetworkObjPtr obj;
1019
    g_autofree xmlNodePtr *nodes = NULL;
1020 1021

    num = virXPathNodeSet("/node/network", ctxt, &nodes);
1022
    if (num < 0)
1023
        return -1;
1024 1025

    for (i = 0; i < num; i++) {
1026
        virNetworkDefPtr def;
C
Cole Robinson 已提交
1027 1028
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file, "network");
        if (!node)
1029
            return -1;
1030

1031
        def = virNetworkDefParseNode(ctxt->doc, node, NULL);
C
Cole Robinson 已提交
1032
        if (!def)
1033
            return -1;
1034

1035
        if (!(obj = virNetworkObjAssignDef(privconn->networks, def, 0))) {
1036
            virNetworkDefFree(def);
1037
            return -1;
1038
        }
1039

1040
        virNetworkObjSetActive(obj, true);
1041
        virNetworkObjEndAPI(&obj);
1042
    }
1043

1044
    return 0;
1045 1046
}

1047

1048
static int
1049
testParseInterfaces(testDriverPtr privconn,
C
Cole Robinson 已提交
1050 1051
                    const char *file,
                    xmlXPathContextPtr ctxt)
1052
{
1053
    int num;
1054 1055
    size_t i;
    virInterfaceObjPtr obj;
1056
    g_autofree xmlNodePtr *nodes = NULL;
1057 1058

    num = virXPathNodeSet("/node/interface", ctxt, &nodes);
1059
    if (num < 0)
1060
        return -1;
1061 1062

    for (i = 0; i < num; i++) {
L
Laine Stump 已提交
1063
        virInterfaceDefPtr def;
C
Cole Robinson 已提交
1064 1065 1066
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "interface");
        if (!node)
1067
            return -1;
L
Laine Stump 已提交
1068

C
Cole Robinson 已提交
1069 1070
        def = virInterfaceDefParseNode(ctxt->doc, node);
        if (!def)
1071
            return -1;
1072

1073
        if (!(obj = virInterfaceObjListAssignDef(privconn->ifaces, def))) {
L
Laine Stump 已提交
1074
            virInterfaceDefFree(def);
1075
            return -1;
L
Laine Stump 已提交
1076
        }
1077

1078
        virInterfaceObjSetActive(obj, true);
1079
        virInterfaceObjEndAPI(&obj);
1080 1081
    }

1082
    return 0;
1083 1084
}

1085

1086
static int
C
Cole Robinson 已提交
1087
testOpenVolumesForPool(const char *file,
1088
                       xmlXPathContextPtr ctxt,
1089 1090
                       virStoragePoolObjPtr obj,
                       int objidx)
1091
{
1092
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(obj);
1093
    size_t i;
1094
    int num;
1095 1096
    g_autofree char *vol_xpath = NULL;
    g_autofree xmlNodePtr *nodes = NULL;
J
Ján Tomko 已提交
1097
    g_autoptr(virStorageVolDef) volDef = NULL;
1098 1099

    /* Find storage volumes */
1100
    vol_xpath = g_strdup_printf("/node/pool[%d]/volume", objidx);
1101 1102

    num = virXPathNodeSet(vol_xpath, ctxt, &nodes);
1103
    if (num < 0)
1104
        return -1;
1105 1106

    for (i = 0; i < num; i++) {
C
Cole Robinson 已提交
1107 1108 1109
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "volume");
        if (!node)
1110
            return -1;
1111

1112
        if (!(volDef = virStorageVolDefParseNode(def, ctxt->doc, node, 0)))
1113
            return -1;
1114

1115
        if (!volDef->target.path) {
1116 1117
            volDef->target.path = g_strdup_printf("%s/%s", def->target.path,
                                                  volDef->name);
1118 1119
        }

1120 1121
        if (!volDef->key)
            volDef->key = g_strdup(volDef->target.path);
1122

1123
        if (virStoragePoolObjAddVol(obj, volDef) < 0)
1124
            return -1;
1125

1126 1127
        def->allocation += volDef->target.allocation;
        def->available = (def->capacity - def->allocation);
1128
        volDef = NULL;
L
Laine Stump 已提交
1129 1130
    }

1131
    return 0;
1132 1133
}

1134

1135
static int
1136
testParseStorage(testDriverPtr privconn,
C
Cole Robinson 已提交
1137 1138
                 const char *file,
                 xmlXPathContextPtr ctxt)
1139
{
1140
    int num;
1141 1142
    size_t i;
    virStoragePoolObjPtr obj;
1143
    g_autofree xmlNodePtr *nodes = NULL;
1144 1145

    num = virXPathNodeSet("/node/pool", ctxt, &nodes);
1146
    if (num < 0)
1147
        return -1;
1148 1149

    for (i = 0; i < num; i++) {
C
Cole Robinson 已提交
1150
        virStoragePoolDefPtr def;
C
Cole Robinson 已提交
1151 1152 1153
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                   "pool");
        if (!node)
1154
            return -1;
C
Cole Robinson 已提交
1155

C
Cole Robinson 已提交
1156 1157
        def = virStoragePoolDefParseNode(ctxt->doc, node);
        if (!def)
1158
            return -1;
C
Cole Robinson 已提交
1159

1160
        if (!(obj = virStoragePoolObjListAdd(privconn->pools, def, 0))) {
C
Cole Robinson 已提交
1161
            virStoragePoolDefFree(def);
1162
            return -1;
C
Cole Robinson 已提交
1163 1164
        }

1165
        if (testStoragePoolObjSetDefaults(obj) == -1) {
1166
            virStoragePoolObjEndAPI(&obj);
1167
            return -1;
1168
        }
1169
        virStoragePoolObjSetActive(obj, true);
1170 1171

        /* Find storage volumes */
C
Cole Robinson 已提交
1172
        if (testOpenVolumesForPool(file, ctxt, obj, i+1) < 0) {
1173
            virStoragePoolObjEndAPI(&obj);
1174
            return -1;
1175 1176
        }

1177
        virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
1178 1179
    }

1180
    return 0;
1181 1182
}

1183

1184
static int
1185
testParseNodedevs(testDriverPtr privconn,
C
Cole Robinson 已提交
1186 1187
                  const char *file,
                  xmlXPathContextPtr ctxt)
1188
{
1189
    int num;
1190 1191
    size_t i;
    virNodeDeviceObjPtr obj;
1192
    g_autofree xmlNodePtr *nodes = NULL;
1193 1194

    num = virXPathNodeSet("/node/device", ctxt, &nodes);
1195
    if (num < 0)
1196
        return -1;
1197 1198

    for (i = 0; i < num; i++) {
1199
        virNodeDeviceDefPtr def;
C
Cole Robinson 已提交
1200 1201 1202
        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
                                                  "nodedev");
        if (!node)
1203
            return -1;
1204

C
Cole Robinson 已提交
1205 1206
        def = virNodeDeviceDefParseNode(ctxt->doc, node, 0, NULL);
        if (!def)
1207
            return -1;
1208

1209
        if (!(obj = virNodeDeviceObjListAssignDef(privconn->devs, def))) {
1210
            virNodeDeviceDefFree(def);
1211
            return -1;
1212
        }
1213

1214
        virNodeDeviceObjSetSkipUpdateCaps(obj, true);
1215
        virNodeDeviceObjEndAPI(&obj);
1216 1217
    }

1218
    return 0;
1219 1220
}

1221
static int
1222
testParseAuthUsers(testDriverPtr privconn,
1223 1224
                   xmlXPathContextPtr ctxt)
{
1225
    int num;
1226
    size_t i;
1227
    g_autofree xmlNodePtr *nodes = NULL;
1228 1229 1230

    num = virXPathNodeSet("/node/auth/user", ctxt, &nodes);
    if (num < 0)
1231
        return -1;
1232 1233 1234

    privconn->numAuths = num;
    if (num && VIR_ALLOC_N(privconn->auths, num) < 0)
1235
        return -1;
1236 1237

    for (i = 0; i < num; i++) {
1238
        g_autofree char *username = NULL;
1239 1240 1241 1242 1243 1244

        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"));
1245
            return -1;
1246 1247
        }
        /* This field is optional. */
1248
        privconn->auths[i].password = virXMLPropString(nodes[i], "password");
1249
        privconn->auths[i].username = g_steal_pointer(&username);
1250 1251
    }

1252
    return 0;
1253
}
1254

C
Cole Robinson 已提交
1255 1256 1257 1258 1259
static int
testOpenParse(testDriverPtr privconn,
              const char *file,
              xmlXPathContextPtr ctxt)
{
1260
    if (!virXMLNodeNameEqual(ctxt->node, "node")) {
C
Cole Robinson 已提交
1261 1262
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("Root element is not 'node'"));
1263
        return -1;
C
Cole Robinson 已提交
1264 1265 1266
    }

    if (testParseNodeInfo(&privconn->nodeInfo, ctxt) < 0)
1267
        return -1;
C
Cole Robinson 已提交
1268
    if (testParseDomains(privconn, file, ctxt) < 0)
1269
        return -1;
C
Cole Robinson 已提交
1270
    if (testParseNetworks(privconn, file, ctxt) < 0)
1271
        return -1;
C
Cole Robinson 已提交
1272
    if (testParseInterfaces(privconn, file, ctxt) < 0)
1273
        return -1;
C
Cole Robinson 已提交
1274
    if (testParseStorage(privconn, file, ctxt) < 0)
1275
        return -1;
C
Cole Robinson 已提交
1276
    if (testParseNodedevs(privconn, file, ctxt) < 0)
1277
        return -1;
C
Cole Robinson 已提交
1278
    if (testParseAuthUsers(privconn, ctxt) < 0)
1279
        return -1;
C
Cole Robinson 已提交
1280 1281 1282 1283

    return 0;
}

1284 1285
/* No shared state between simultaneous test connections initialized
 * from a file.  */
1286 1287 1288 1289 1290
static int
testOpenFromFile(virConnectPtr conn, const char *file)
{
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
1291
    testDriverPtr privconn;
1292

1293
    if (!(privconn = testDriverNew()))
1294
        return VIR_DRV_OPEN_ERROR;
1295

1296
    virObjectLock(privconn);
1297 1298 1299 1300 1301
    conn->privateData = privconn;

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

1302
    if (!(doc = virXMLParseFileCtxt(file, &ctxt)))
1303 1304 1305 1306 1307
        goto error;

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

C
Cole Robinson 已提交
1308
    if (testOpenParse(privconn, file, ctxt) < 0)
1309
        goto error;
1310

J
Jim Meyering 已提交
1311
    xmlXPathFreeContext(ctxt);
1312
    xmlFreeDoc(doc);
1313
    virObjectUnlock(privconn);
1314

1315
    return VIR_DRV_OPEN_SUCCESS;
1316 1317

 error:
J
Jim Meyering 已提交
1318
    xmlXPathFreeContext(ctxt);
1319
    xmlFreeDoc(doc);
1320
    virObjectUnref(privconn);
1321
    conn->privateData = NULL;
1322
    return VIR_DRV_OPEN_ERROR;
1323 1324
}

1325 1326 1327 1328 1329 1330
/* 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)
{
1331
    int ret = VIR_DRV_OPEN_ERROR;
1332
    testDriverPtr privconn = NULL;
1333 1334
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
1335
    size_t i;
1336 1337

    virMutexLock(&defaultLock);
1338 1339
    if (defaultPrivconn) {
        conn->privateData = virObjectRef(defaultPrivconn);
1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352
        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;
1353 1354 1355 1356
    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;
1357
    }
1358
    for (i = 0; i < 16; i++) {
1359 1360 1361
        virBitmapPtr siblings = virBitmapNew(16);
        if (!siblings)
            goto error;
1362 1363 1364 1365 1366
        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;
1367 1368 1369 1370 1371
    }

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

1372 1373
    if (!(doc = virXMLParseStringCtxt(defaultConnXML,
                                      _("(test driver)"), &ctxt)))
1374 1375
        goto error;

1376
    if (testOpenParse(privconn, NULL, ctxt) < 0)
1377 1378
        goto error;

1379
    defaultPrivconn = privconn;
1380 1381 1382
    ret = VIR_DRV_OPEN_SUCCESS;
 cleanup:
    virMutexUnlock(&defaultLock);
1383 1384
    xmlXPathFreeContext(ctxt);
    xmlFreeDoc(doc);
1385
    return ret;
1386 1387

 error:
1388
    virObjectUnref(privconn);
1389
    conn->privateData = NULL;
1390
    goto cleanup;
1391 1392
}

1393 1394 1395 1396
static int
testConnectAuthenticate(virConnectPtr conn,
                        virConnectAuthPtr auth)
{
1397
    testDriverPtr privconn = conn->privateData;
1398 1399
    int ret = -1;
    ssize_t i;
1400 1401
    g_autofree char *username = NULL;
    g_autofree char *password = NULL;
1402

1403
    virObjectLock(privconn);
1404
    if (privconn->numAuths == 0) {
1405
        virObjectUnlock(privconn);
1406
        return 0;
1407
    }
1408 1409 1410 1411

    /* Authentication is required because the test XML contains a
     * non-empty <auth/> section.  First we must ask for a username.
     */
1412 1413
    if (!(username = virAuthGetUsername(conn, auth, "test", NULL,
                                        "localhost"/*?*/)))
1414 1415 1416 1417 1418 1419 1420 1421 1422
        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;

1423
 found_user:
1424 1425
    /* Even if we didn't find the user, we still ask for a password. */
    if (i == -1 || privconn->auths[i].password != NULL) {
1426 1427
        if (!(password = virAuthGetPassword(conn, auth, "test", username,
                                            "localhost")))
1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438
            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;
1439
 cleanup:
1440
    virObjectUnlock(privconn);
1441 1442
    return ret;
}
1443

1444 1445 1446 1447

static void
testDriverCloseInternal(testDriverPtr driver)
{
1448 1449 1450
    virMutexLock(&defaultLock);
    bool disposed = !virObjectUnref(driver);
    if (disposed && driver == defaultPrivconn)
1451
        defaultPrivconn = NULL;
1452
    virMutexUnlock(&defaultLock);
1453 1454 1455 1456 1457 1458
}


static virDrvOpenStatus
testConnectOpen(virConnectPtr conn,
                virConnectAuthPtr auth,
J
Ján Tomko 已提交
1459
                virConfPtr conf G_GNUC_UNUSED,
1460
                unsigned int flags)
1461
{
1462
    int ret;
1463

E
Eric Blake 已提交
1464 1465
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

1466 1467
    if (conn->uri->path[0] == '\0' ||
        (conn->uri->path[0] == '/' && conn->uri->path[1] == '\0')) {
1468 1469
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("testOpen: supply a path or use test:///default"));
1470 1471
        return VIR_DRV_OPEN_ERROR;
    }
1472

1473
    if (STREQ(conn->uri->path, "/default"))
1474 1475
        ret = testOpenDefault(conn);
    else
1476
        ret = testOpenFromFile(conn,
1477
                               conn->uri->path);
1478

1479 1480 1481
    if (ret != VIR_DRV_OPEN_SUCCESS)
        return ret;

1482
    /* Fake authentication. */
1483 1484 1485
    if (testConnectAuthenticate(conn, auth) < 0) {
        testDriverCloseInternal(conn->privateData);
        conn->privateData = NULL;
1486
        return VIR_DRV_OPEN_ERROR;
1487
    }
1488

1489
    return VIR_DRV_OPEN_SUCCESS;
1490 1491
}

1492

1493 1494 1495 1496
static int
testConnectClose(virConnectPtr conn)
{
    testDriverCloseInternal(conn->privateData);
1497
    conn->privateData = NULL;
1498
    return 0;
1499 1500
}

1501

J
Ján Tomko 已提交
1502
static int testConnectGetVersion(virConnectPtr conn G_GNUC_UNUSED,
1503
                                 unsigned long *hvVer)
1504
{
1505
    *hvVer = 2;
1506
    return 0;
1507 1508
}

J
Ján Tomko 已提交
1509
static char *testConnectGetHostname(virConnectPtr conn G_GNUC_UNUSED)
1510 1511 1512 1513 1514
{
    return virGetHostname();
}


J
Ján Tomko 已提交
1515
static int testConnectIsSecure(virConnectPtr conn G_GNUC_UNUSED)
1516 1517 1518 1519
{
    return 1;
}

J
Ján Tomko 已提交
1520
static int testConnectIsEncrypted(virConnectPtr conn G_GNUC_UNUSED)
1521 1522 1523 1524
{
    return 0;
}

J
Ján Tomko 已提交
1525
static int testConnectIsAlive(virConnectPtr conn G_GNUC_UNUSED)
1526 1527 1528 1529
{
    return 1;
}

J
Ján Tomko 已提交
1530 1531
static int testConnectGetMaxVcpus(virConnectPtr conn G_GNUC_UNUSED,
                                  const char *type G_GNUC_UNUSED)
1532 1533 1534 1535
{
    return 32;
}

1536
static char *
J
Ján Tomko 已提交
1537
testConnectBaselineCPU(virConnectPtr conn G_GNUC_UNUSED,
1538 1539 1540 1541
                       const char **xmlCPUs,
                       unsigned int ncpus,
                       unsigned int flags)
{
J
Jiri Denemark 已提交
1542 1543 1544
    virCPUDefPtr *cpus = NULL;
    virCPUDefPtr cpu = NULL;
    char *cpustr = NULL;
1545 1546 1547

    virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, NULL);

J
Jiri Denemark 已提交
1548 1549 1550
    if (!(cpus = virCPUDefListParse(xmlCPUs, ncpus, VIR_CPU_TYPE_HOST)))
        goto cleanup;

1551
    if (!(cpu = virCPUBaseline(VIR_ARCH_NONE, cpus, ncpus, NULL, NULL, false)))
J
Jiri Denemark 已提交
1552 1553 1554 1555 1556 1557
        goto cleanup;

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

1558
    cpustr = virCPUDefFormat(cpu, NULL);
J
Jiri Denemark 已提交
1559 1560 1561 1562

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

J
Jiri Denemark 已提交
1564
    return cpustr;
1565 1566
}

1567 1568
static int testNodeGetInfo(virConnectPtr conn,
                           virNodeInfoPtr info)
1569
{
1570
    testDriverPtr privconn = conn->privateData;
1571
    virObjectLock(privconn);
1572
    memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo));
1573
    virObjectUnlock(privconn);
1574
    return 0;
1575 1576
}

1577
static char *testConnectGetCapabilities(virConnectPtr conn)
1578
{
1579
    testDriverPtr privconn = conn->privateData;
1580
    char *xml;
1581
    virObjectLock(privconn);
1582
    xml = virCapabilitiesFormatXML(privconn->caps);
1583
    virObjectUnlock(privconn);
1584
    return xml;
1585 1586
}

1587
static char *
J
Ján Tomko 已提交
1588
testConnectGetSysinfo(virConnectPtr conn G_GNUC_UNUSED,
1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602
                      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);

1603
    ret = g_strdup(sysinfo);
1604 1605 1606
    return ret;
}

1607
static const char *
J
Ján Tomko 已提交
1608
testConnectGetType(virConnectPtr conn G_GNUC_UNUSED)
1609 1610 1611 1612
{
    return "TEST";
}

1613 1614

static int
J
Ján Tomko 已提交
1615
testConnectSupportsFeature(virConnectPtr conn G_GNUC_UNUSED,
1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640
                           int feature)
{
    switch ((virDrvFeature) feature) {
    case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
        return 1;
    case VIR_DRV_FEATURE_MIGRATION_V2:
    case VIR_DRV_FEATURE_MIGRATION_V3:
    case VIR_DRV_FEATURE_MIGRATION_P2P:
    case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
    case VIR_DRV_FEATURE_FD_PASSING:
    case VIR_DRV_FEATURE_XML_MIGRATABLE:
    case VIR_DRV_FEATURE_MIGRATION_OFFLINE:
    case VIR_DRV_FEATURE_MIGRATION_PARAMS:
    case VIR_DRV_FEATURE_MIGRATION_DIRECT:
    case VIR_DRV_FEATURE_MIGRATION_V1:
    case VIR_DRV_FEATURE_PROGRAM_KEEPALIVE:
    case VIR_DRV_FEATURE_REMOTE:
    case VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK:
    case VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK:
    default:
        return 0;
    }
}


1641
static int testConnectNumOfDomains(virConnectPtr conn)
1642
{
1643
    testDriverPtr privconn = conn->privateData;
1644
    int count;
1645

1646
    virObjectLock(privconn);
1647
    count = virDomainObjListNumOfDomains(privconn->domains, true, NULL, NULL);
1648
    virObjectUnlock(privconn);
1649

1650
    return count;
1651 1652
}

1653 1654 1655
static int testDomainIsActive(virDomainPtr dom)
{
    virDomainObjPtr obj;
1656
    int ret;
1657

1658 1659
    if (!(obj = testDomObjFromDomain(dom)))
        return -1;
1660

1661 1662
    ret = virDomainObjIsActive(obj);
    virDomainObjEndAPI(&obj);
1663 1664 1665 1666 1667 1668
    return ret;
}

static int testDomainIsPersistent(virDomainPtr dom)
{
    virDomainObjPtr obj;
1669 1670 1671 1672
    int ret;

    if (!(obj = testDomObjFromDomain(dom)))
        return -1;
1673 1674 1675

    ret = obj->persistent;

1676
    virDomainObjEndAPI(&obj);
1677 1678 1679
    return ret;
}

J
Ján Tomko 已提交
1680
static int testDomainIsUpdated(virDomainPtr dom G_GNUC_UNUSED)
1681 1682 1683 1684
{
    return 0;
}

1685
static virDomainPtr
1686
testDomainCreateXML(virConnectPtr conn, const char *xml,
1687
                      unsigned int flags)
1688
{
1689
    testDriverPtr privconn = conn->privateData;
1690
    virDomainPtr ret = NULL;
1691
    virDomainDefPtr def;
1692
    virDomainObjPtr dom = NULL;
1693
    virObjectEventPtr event = NULL;
1694
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
1695

1696 1697 1698
    virCheckFlags(VIR_DOMAIN_START_VALIDATE, NULL);

    if (flags & VIR_DOMAIN_START_VALIDATE)
1699
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
1700

1701
    virObjectLock(privconn);
1702
    if ((def = virDomainDefParseString(xml, privconn->xmlopt,
1703
                                       NULL, parse_flags)) == NULL)
1704
        goto cleanup;
1705

1706
    if (testDomainGenerateIfnames(def) < 0)
1707
        goto cleanup;
1708
    if (!(dom = virDomainObjListAdd(privconn->domains,
1709
                                    def,
1710
                                    privconn->xmlopt,
1711
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
1712 1713
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
1714 1715
        goto cleanup;
    def = NULL;
1716

1717
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_BOOTED) < 0) {
1718
        if (!dom->persistent)
1719
            virDomainObjListRemove(privconn->domains, dom);
1720
        goto cleanup;
1721
    }
1722

1723
    event = virDomainEventLifecycleNewFromObj(dom,
1724 1725 1726
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);

1727
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
1728

1729
 cleanup:
1730
    virDomainObjEndAPI(&dom);
1731
    virObjectEventStateQueue(privconn->eventState, event);
1732
    virDomainDefFree(def);
1733
    virObjectUnlock(privconn);
1734
    return ret;
1735 1736 1737
}


1738 1739 1740
static virDomainPtr
testDomainCreateXMLWithFiles(virConnectPtr conn,
                             const char *xml,
J
Ján Tomko 已提交
1741 1742
                             unsigned int nfiles G_GNUC_UNUSED,
                             int *files G_GNUC_UNUSED,
1743 1744 1745 1746 1747 1748
                             unsigned int flags)
{
    return testDomainCreateXML(conn, xml, flags);
}


1749
static virDomainPtr testDomainLookupByID(virConnectPtr conn,
1750
                                         int id)
1751
{
1752
    testDriverPtr privconn = conn->privateData;
1753 1754
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1755

1756
    if (!(dom = virDomainObjListFindByID(privconn->domains, id))) {
1757
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1758
        return NULL;
1759 1760
    }

1761
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
1762

1763
    virDomainObjEndAPI(&dom);
1764
    return ret;
1765 1766
}

1767
static virDomainPtr testDomainLookupByUUID(virConnectPtr conn,
1768
                                           const unsigned char *uuid)
1769
{
1770
    testDriverPtr privconn = conn->privateData;
1771
    virDomainPtr ret = NULL;
1772
    virDomainObjPtr dom;
1773

1774
    if (!(dom = virDomainObjListFindByUUID(privconn->domains, uuid))) {
1775
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1776
        return NULL;
1777
    }
1778

1779
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
1780

1781
    virDomainObjEndAPI(&dom);
1782
    return ret;
1783 1784
}

1785
static virDomainPtr testDomainLookupByName(virConnectPtr conn,
1786
                                           const char *name)
1787
{
1788
    testDriverPtr privconn = conn->privateData;
1789 1790
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1791

1792
    if (!(dom = virDomainObjListFindByName(privconn->domains, name))) {
1793
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
1794
        goto cleanup;
1795
    }
1796

1797
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
1798

1799
 cleanup:
1800
    virDomainObjEndAPI(&dom);
1801
    return ret;
1802 1803
}

1804 1805 1806
static int testConnectListDomains(virConnectPtr conn,
                                  int *ids,
                                  int maxids)
1807
{
1808
    testDriverPtr privconn = conn->privateData;
1809

1810 1811
    return virDomainObjListGetActiveIDs(privconn->domains, ids, maxids,
                                        NULL, NULL);
1812 1813
}

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

1822 1823
    virCheckFlags(VIR_DOMAIN_DESTROY_GRACEFUL, -1);

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

1827
    if (virDomainObjCheckActive(privdom) < 0)
1828 1829
        goto cleanup;

J
Jiri Denemark 已提交
1830
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_DESTROYED);
1831
    event = virDomainEventLifecycleNewFromObj(privdom,
1832 1833
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
1834

1835
    if (!privdom->persistent)
1836
        virDomainObjListRemove(privconn->domains, privdom);
1837 1838

    ret = 0;
1839
 cleanup:
1840
    virDomainObjEndAPI(&privdom);
1841
    virObjectEventStateQueue(privconn->eventState, event);
1842
    return ret;
1843 1844
}

1845 1846 1847 1848 1849
static int testDomainDestroy(virDomainPtr domain)
{
    return testDomainDestroyFlags(domain, 0);
}

1850
static int testDomainResume(virDomainPtr domain)
1851
{
1852
    testDriverPtr privconn = domain->conn->privateData;
1853
    virDomainObjPtr privdom;
1854
    virObjectEventPtr event = NULL;
1855
    int ret = -1;
1856

1857 1858
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1859

J
Jiri Denemark 已提交
1860
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_PAUSED) {
1861 1862
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"),
                       domain->name);
1863
        goto cleanup;
1864
    }
1865

J
Jiri Denemark 已提交
1866 1867
    virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
                         VIR_DOMAIN_RUNNING_UNPAUSED);
1868
    event = virDomainEventLifecycleNewFromObj(privdom,
1869 1870
                                     VIR_DOMAIN_EVENT_RESUMED,
                                     VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
1871 1872
    ret = 0;

1873
 cleanup:
1874
    virDomainObjEndAPI(&privdom);
1875
    virObjectEventStateQueue(privconn->eventState, event);
1876
    return ret;
1877 1878
}

1879
static int testDomainSuspend(virDomainPtr domain)
1880
{
1881
    testDriverPtr privconn = domain->conn->privateData;
1882
    virDomainObjPtr privdom;
1883
    virObjectEventPtr event = NULL;
1884
    int ret = -1;
J
Jiri Denemark 已提交
1885
    int state;
1886

1887 1888
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
1889

J
Jiri Denemark 已提交
1890 1891
    state = virDomainObjGetState(privdom, NULL);
    if (state == VIR_DOMAIN_SHUTOFF || state == VIR_DOMAIN_PAUSED) {
1892 1893
        virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"),
                       domain->name);
1894
        goto cleanup;
1895
    }
1896

J
Jiri Denemark 已提交
1897
    virDomainObjSetState(privdom, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
1898
    event = virDomainEventLifecycleNewFromObj(privdom,
1899 1900
                                     VIR_DOMAIN_EVENT_SUSPENDED,
                                     VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
1901 1902
    ret = 0;

1903
 cleanup:
1904
    virDomainObjEndAPI(&privdom);
1905
    virObjectEventStateQueue(privconn->eventState, event);
1906
    return ret;
1907 1908
}

1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942

static void
testDomainActionSetState(virDomainObjPtr dom,
                         int lifecycle_type)
{
    switch (lifecycle_type) {
    case VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY:
        virDomainObjSetState(dom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
        break;

    case VIR_DOMAIN_LIFECYCLE_ACTION_RESTART:
        virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
        break;

    case VIR_DOMAIN_LIFECYCLE_ACTION_PRESERVE:
        virDomainObjSetState(dom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
        break;

    case VIR_DOMAIN_LIFECYCLE_ACTION_RESTART_RENAME:
        virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_BOOTED);
        break;

    default:
        virDomainObjSetState(dom, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
        break;
    }
}


1943
static int testDomainShutdownFlags(virDomainPtr domain,
1944
                                   unsigned int flags)
1945
{
1946
    testDriverPtr privconn = domain->conn->privateData;
1947
    virDomainObjPtr privdom;
1948
    virObjectEventPtr event = NULL;
1949
    int ret = -1;
1950

1951 1952
    virCheckFlags(0, -1);

1953

1954
    if (!(privdom = testDomObjFromDomain(domain)))
1955
        goto cleanup;
1956

J
Jiri Denemark 已提交
1957
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
1958 1959
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("domain '%s' not running"), domain->name);
1960
        goto cleanup;
1961
    }
1962

1963
    testDomainActionSetState(privdom, privdom->def->onPoweroff);
1964

1965 1966 1967 1968 1969 1970 1971 1972 1973
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
        event = virDomainEventLifecycleNewFromObj(privdom,
                                                  VIR_DOMAIN_EVENT_STOPPED,
                                                  VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);

        if (!privdom->persistent)
            virDomainObjListRemove(privconn->domains, privdom);
    }
1974

1975
    ret = 0;
1976
 cleanup:
1977
    virDomainObjEndAPI(&privdom);
1978
    virObjectEventStateQueue(privconn->eventState, event);
1979
    return ret;
1980 1981
}

1982
static int testDomainShutdown(virDomainPtr domain)
1983
{
1984
    return testDomainShutdownFlags(domain, 0);
1985 1986
}

1987
/* Similar behaviour as shutdown */
1988
static int testDomainReboot(virDomainPtr domain,
1989
                            unsigned int flags)
1990
{
1991
    testDriverPtr privconn = domain->conn->privateData;
1992
    virDomainObjPtr privdom;
1993
    virObjectEventPtr event = NULL;
1994
    int ret = -1;
1995

1996 1997 1998 1999 2000 2001
    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);
2002

2003
    if (!(privdom = testDomObjFromDomain(domain)))
2004
        goto cleanup;
2005

2006
    if (virDomainObjCheckActive(privdom) < 0)
2007 2008
        goto cleanup;

2009
    testDomainActionSetState(privdom, privdom->def->onReboot);
2010

J
Jiri Denemark 已提交
2011 2012
    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
2013
        event = virDomainEventLifecycleNewFromObj(privdom,
2014 2015
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
2016

2017
        if (!privdom->persistent)
2018
            virDomainObjListRemove(privconn->domains, privdom);
2019 2020
    }

2021
    ret = 0;
2022
 cleanup:
2023
    virDomainObjEndAPI(&privdom);
2024
    virObjectEventStateQueue(privconn->eventState, event);
2025
    return ret;
2026 2027
}

2028

2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050
static int
testDomainReset(virDomainPtr dom,
                unsigned int flags)
{
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(0, -1);

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

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

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


2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065
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;

2066
    ret = g_strdup_printf("%shost", domain->name);
2067 2068 2069 2070 2071 2072 2073

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


2074
static int testDomainGetInfo(virDomainPtr domain,
2075
                             virDomainInfoPtr info)
2076
{
2077 2078
    virDomainObjPtr privdom;

2079 2080
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2081

J
Jiri Denemark 已提交
2082
    info->state = virDomainObjGetState(privdom, NULL);
2083
    info->memory = privdom->def->mem.cur_balloon;
2084
    info->maxMem = virDomainDefGetMemoryTotal(privdom->def);
2085
    info->nrVirtCpu = virDomainDefGetVcpus(privdom->def);
2086
    info->cpuTime = g_get_real_time() * 1000;
2087

2088
    virDomainObjEndAPI(&privdom);
2089
    return 0;
2090 2091
}

2092 2093 2094 2095 2096 2097 2098 2099 2100 2101
static int
testDomainGetState(virDomainPtr domain,
                   int *state,
                   int *reason,
                   unsigned int flags)
{
    virDomainObjPtr privdom;

    virCheckFlags(0, -1);

2102 2103
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
2104

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

2107
    virDomainObjEndAPI(&privdom);
2108 2109

    return 0;
2110 2111
}

2112
static int
2113
testDomainGetTime(virDomainPtr dom,
2114 2115 2116 2117
                  long long *seconds,
                  unsigned int *nseconds,
                  unsigned int flags)
{
2118
    virDomainObjPtr vm = NULL;
2119
    testDomainObjPrivatePtr priv;
2120 2121
    int ret = -1;

2122 2123
    virCheckFlags(0, -1);

2124 2125 2126 2127 2128 2129 2130 2131 2132
    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;
    }

2133 2134 2135
    priv = vm->privateData;
    *seconds = priv->seconds;
    *nseconds = priv->nseconds;
2136

2137 2138 2139 2140
    ret = 0;
 cleanup:
    virDomainObjEndAPI(&vm);
    return ret;
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

static int
testDomainSetTime(virDomainPtr dom,
                  long long seconds,
                  unsigned int nseconds,
                  unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    testDomainObjPrivatePtr priv;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_TIME_SYNC, ret);

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

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

    priv = vm->privateData;
    priv->seconds = seconds;
    priv->nseconds = nseconds;

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

2172 2173
#define TEST_SAVE_MAGIC "TestGuestMagic"

2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186

/**
 * 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)
2187
{
2188
    int len;
2189
    int fd = -1;
2190
    g_autofree char *xml = NULL;
2191

2192
    xml = virDomainDefFormat(def, driver->xmlopt,
2193
                             VIR_DOMAIN_DEF_FORMAT_SECURE);
C
Cole Robinson 已提交
2194

2195
    if (xml == NULL) {
2196
        virReportSystemError(errno,
2197
                             _("saving domain '%s' failed to allocate space for metadata"),
2198 2199
                             def->name);
        goto error;
2200
    }
2201 2202

    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
2203
        virReportSystemError(errno,
2204
                             _("saving domain '%s' to '%s': open failed"),
2205 2206
                             def->name, path);
        goto error;
2207
    }
2208

2209
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
2210
        virReportSystemError(errno,
2211
                             _("saving domain '%s' to '%s': write failed"),
2212 2213
                             def->name, path);
        goto error;
2214
    }
2215 2216

    len = strlen(xml);
2217
    if (safewrite(fd, (char*)&len, sizeof(len)) < 0) {
2218
        virReportSystemError(errno,
2219
                             _("saving domain '%s' to '%s': write failed"),
2220 2221
                             def->name, path);
        goto error;
2222
    }
2223

2224
    if (safewrite(fd, xml, len) < 0) {
2225
        virReportSystemError(errno,
2226
                             _("saving domain '%s' to '%s': write failed"),
2227 2228
                             def->name, path);
        goto error;
2229
    }
2230

2231
    if (VIR_CLOSE(fd) < 0) {
2232
        virReportSystemError(errno,
2233
                             _("saving domain '%s' to '%s': write failed"),
2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250
                             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;
}


2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268
/**
 * 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;
2269
    g_autofree char *xml = NULL;
2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307

    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';

2308
    if (!(def = virDomainDefParseString(xml, driver->xmlopt, NULL,
2309 2310 2311 2312
                                        VIR_DOMAIN_DEF_PARSE_INACTIVE |
                                        VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
        goto error;

2313
    *ret_def = g_steal_pointer(&def);
2314 2315 2316 2317 2318 2319 2320 2321 2322
    return fd;

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


2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337
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;
2338
    }
2339 2340 2341 2342 2343 2344 2345 2346 2347

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

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

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

J
Jiri Denemark 已提交
2349
    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SAVED);
2350
    event = virDomainEventLifecycleNewFromObj(privdom,
2351 2352
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
2353

2354
    if (!privdom->persistent)
2355
        virDomainObjListRemove(privconn->domains, privdom);
2356

2357
    ret = 0;
2358
 cleanup:
2359
    virDomainObjEndAPI(&privdom);
2360
    virObjectEventStateQueue(privconn->eventState, event);
2361
    return ret;
2362 2363
}

2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375
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)
2376
{
2377
    testDriverPtr privconn = conn->privateData;
2378 2379
    int fd = -1;
    virDomainDefPtr def = NULL;
2380
    virDomainObjPtr dom = NULL;
2381
    virObjectEventPtr event = NULL;
2382
    int ret = -1;
2383

2384 2385
    virCheckFlags(0, -1);
    if (dxml) {
2386 2387
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
2388 2389 2390
        return -1;
    }

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

2394
    if (testDomainGenerateIfnames(def) < 0)
2395
        goto cleanup;
2396
    if (!(dom = virDomainObjListAdd(privconn->domains,
2397
                                    def,
2398
                                    privconn->xmlopt,
2399 2400 2401
                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                    NULL)))
2402 2403
        goto cleanup;
    def = NULL;
2404

2405
    if (testDomainStartState(privconn, dom, VIR_DOMAIN_RUNNING_RESTORED) < 0) {
2406
        if (!dom->persistent)
2407
            virDomainObjListRemove(privconn->domains, dom);
2408
        goto cleanup;
2409
    }
2410

2411
    event = virDomainEventLifecycleNewFromObj(dom,
2412 2413
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
2414
    ret = 0;
2415

2416
 cleanup:
2417
    virDomainDefFree(def);
2418
    VIR_FORCE_CLOSE(fd);
2419
    virDomainObjEndAPI(&dom);
2420
    virObjectEventStateQueue(privconn->eventState, event);
2421
    return ret;
2422 2423
}

2424 2425 2426 2427 2428 2429 2430
static int
testDomainRestore(virConnectPtr conn,
                  const char *path)
{
    return testDomainRestoreFlags(conn, path, NULL, 0);
}

2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450

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);

2451
    if ((newdef = virDomainDefParseString(dxml, privconn->xmlopt, NULL,
2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466
                                          VIR_DOMAIN_DEF_PARSE_INACTIVE)) == NULL)
        goto cleanup;

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

    ret = 0;

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


2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481
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;

2482
    ret = virDomainDefFormat(def, privconn->xmlopt,
2483
                             VIR_DOMAIN_DEF_FORMAT_SECURE);
2484 2485 2486 2487 2488 2489 2490 2491

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


2492 2493 2494 2495
static int testDomainCoreDumpWithFormat(virDomainPtr domain,
                                        const char *to,
                                        unsigned int dumpformat,
                                        unsigned int flags)
2496
{
2497
    testDriverPtr privconn = domain->conn->privateData;
2498
    int fd = -1;
2499
    virDomainObjPtr privdom;
2500
    virObjectEventPtr event = NULL;
2501
    int ret = -1;
2502

E
Eric Blake 已提交
2503 2504
    virCheckFlags(VIR_DUMP_CRASH, -1);

2505

2506
    if (!(privdom = testDomObjFromDomain(domain)))
2507
        goto cleanup;
2508

2509
    if (virDomainObjCheckActive(privdom) < 0)
2510 2511
        goto cleanup;

2512
    if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
2513
        virReportSystemError(errno,
2514 2515
                             _("domain '%s' coredump: failed to open %s"),
                             domain->name, to);
2516
        goto cleanup;
2517
    }
2518
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
2519
        virReportSystemError(errno,
2520 2521
                             _("domain '%s' coredump: failed to write header to %s"),
                             domain->name, to);
2522
        goto cleanup;
2523
    }
2524
    if (VIR_CLOSE(fd) < 0) {
2525
        virReportSystemError(errno,
2526 2527
                             _("domain '%s' coredump: write failed: %s"),
                             domain->name, to);
2528
        goto cleanup;
2529
    }
2530

2531 2532 2533 2534 2535 2536 2537
    /* 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;
    }

2538
    if (flags & VIR_DUMP_CRASH) {
J
Jiri Denemark 已提交
2539
        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_CRASHED);
2540
        event = virDomainEventLifecycleNewFromObj(privdom,
2541 2542
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
2543
        if (!privdom->persistent)
2544
            virDomainObjListRemove(privconn->domains, privdom);
2545
    }
2546

2547
    ret = 0;
2548
 cleanup:
2549
    VIR_FORCE_CLOSE(fd);
2550
    virDomainObjEndAPI(&privdom);
2551
    virObjectEventStateQueue(privconn->eventState, event);
2552
    return ret;
2553 2554
}

2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566

static int
testDomainCoreDump(virDomainPtr domain,
                   const char *to,
                   unsigned int flags)
{
    return testDomainCoreDumpWithFormat(domain, to,
                                        VIR_DOMAIN_CORE_DUMP_FORMAT_RAW, flags);
}


static char *
J
Ján Tomko 已提交
2567
testDomainGetOSType(virDomainPtr dom G_GNUC_UNUSED)
2568
{
2569 2570
    char *ret;

2571
    ret = g_strdup("linux");
2572
    return ret;
2573 2574
}

2575

2576
static int
J
Ján Tomko 已提交
2577 2578
testDomainGetLaunchSecurityInfo(virDomainPtr domain G_GNUC_UNUSED,
                                virTypedParameterPtr *params G_GNUC_UNUSED,
2579 2580 2581 2582 2583 2584 2585 2586 2587 2588
                                int *nparams,
                                unsigned int flags)
{
    virCheckFlags(0, -1);

    *nparams = 0;
    return 0;
}


2589 2590
static unsigned long long
testDomainGetMaxMemory(virDomainPtr domain)
2591
{
2592
    virDomainObjPtr privdom;
2593
    unsigned long long ret = 0;
2594

2595 2596
    if (!(privdom = testDomObjFromDomain(domain)))
        return 0;
2597

2598
    ret = virDomainDefGetMemoryTotal(privdom->def);
2599

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

2604

2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638

static int testDomainSetMemoryStatsPeriod(virDomainPtr dom,
                                          int period,
                                          unsigned int flags)
{
    virDomainObjPtr vm;
    virDomainDefPtr def;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

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

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

    if (!virDomainDefHasMemballoon(def)) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("No memory balloon device configured, "
                         "can not set the collection period"));
        goto cleanup;
    }

    def->memballoon->period = period;

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


E
Eric Blake 已提交
2639 2640 2641
static int testDomainSetMemoryFlags(virDomainPtr domain,
                                    unsigned long memory,
                                    unsigned int flags)
2642
{
2643 2644
    virDomainObjPtr vm;
    virDomainDefPtr def;
2645
    int ret = -1;
2646
    bool live = false;
2647

2648 2649 2650
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
                  VIR_DOMAIN_MEM_MAXIMUM, -1);
E
Eric Blake 已提交
2651

2652
    if (!(vm = testDomObjFromDomain(domain)))
2653
        return -1;
2654

2655
    if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
2656
        goto cleanup;
2657 2658

    if (flags & VIR_DOMAIN_MEM_MAXIMUM) {
2659
        if (live) {
2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("cannot resize the maximum memory on an "
                             "active domain"));
            goto cleanup;
        }

        if (virDomainNumaGetNodeCount(def->numa) > 0) {
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("initial memory size of a domain with NUMA "
                             "nodes cannot be modified with this API"));
            goto cleanup;
        }

        if (def->mem.max_memory && def->mem.max_memory < memory) {
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("cannot set initial memory size greater than "
                             "the maximum memory size"));
            goto cleanup;
        }

        virDomainDefSetMemoryTotal(def, memory);

        if (def->mem.cur_balloon > memory)
            def->mem.cur_balloon = memory;
    } else {
        if (memory > virDomainDefGetMemoryTotal(def)) {
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("cannot set memory higher than max memory"));
            goto cleanup;
        }

        def->mem.cur_balloon = memory;
2692
    }
2693

2694
    ret = 0;
2695
 cleanup:
2696
    virDomainObjEndAPI(&vm);
2697
    return ret;
2698 2699
}

E
Eric Blake 已提交
2700 2701 2702
static int testDomainSetMemory(virDomainPtr domain,
                               unsigned long memory)
{
2703
    return testDomainSetMemoryFlags(domain, memory, VIR_DOMAIN_AFFECT_LIVE);
E
Eric Blake 已提交
2704 2705
}

2706 2707 2708 2709 2710 2711 2712 2713

static int testDomainSetMaxMemory(virDomainPtr domain,
                                  unsigned long memory)
{
    return testDomainSetMemoryFlags(domain, memory, VIR_DOMAIN_MEM_MAXIMUM);
}


2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756
static int
testDomainPinEmulator(virDomainPtr dom,
                      unsigned char *cpumap,
                      int maplen,
                      unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    virBitmapPtr pcpumap = NULL;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

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

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

    if (!(pcpumap = virBitmapNewData(cpumap, maplen)))
        goto cleanup;

    if (virBitmapIsAllClear(pcpumap)) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("Empty cpu list for pinning"));
        goto cleanup;
    }

    virBitmapFree(def->cputune.emulatorpin);
    def->cputune.emulatorpin = NULL;

    if (!(def->cputune.emulatorpin = virBitmapNewCopy(pcpumap)))
        goto cleanup;

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


2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802
static int
testDomainGetEmulatorPinInfo(virDomainPtr dom,
                             unsigned char *cpumaps,
                             int maplen,
                             unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    virBitmapPtr cpumask = NULL;
    virBitmapPtr bitmap = NULL;
    int hostcpus;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

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

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

    if ((hostcpus = virHostCPUGetCount()) < 0)
        goto cleanup;

    if (def->cputune.emulatorpin) {
        cpumask = def->cputune.emulatorpin;
    } else if (def->cpumask) {
        cpumask = def->cpumask;
    } else {
        if (!(bitmap = virBitmapNew(hostcpus)))
            goto cleanup;
        virBitmapSetAll(bitmap);
        cpumask = bitmap;
    }

    virBitmapToDataBuf(cpumask, cpumaps, maplen);

    ret = 1;
 cleanup:
    virDomainObjEndAPI(&vm);
    virBitmapFree(bitmap);
    return ret;
}


2803 2804
static int
testDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
C
Cole Robinson 已提交
2805
{
2806 2807 2808 2809
    virDomainObjPtr vm;
    virDomainDefPtr def;
    int ret = -1;

2810 2811
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2812 2813
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

2814 2815
    if (!(vm = testDomObjFromDomain(domain)))
        return -1;
2816

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

2820 2821 2822
    if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
        ret = virDomainDefGetVcpusMax(def);
    else
2823
        ret = virDomainDefGetVcpus(def);
2824

2825
 cleanup:
2826
    virDomainObjEndAPI(&vm);
2827
    return ret;
C
Cole Robinson 已提交
2828 2829
}

2830 2831 2832
static int
testDomainGetMaxVcpus(virDomainPtr domain)
{
2833
    return testDomainGetVcpusFlags(domain, (VIR_DOMAIN_AFFECT_LIVE |
2834 2835 2836 2837 2838 2839 2840
                                            VIR_DOMAIN_VCPU_MAXIMUM));
}

static int
testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
                        unsigned int flags)
{
2841
    testDriverPtr driver = domain->conn->privateData;
2842
    virDomainObjPtr privdom = NULL;
2843
    virDomainDefPtr def;
2844
    virDomainDefPtr persistentDef;
C
Cole Robinson 已提交
2845 2846
    int ret = -1, maxvcpus;

2847 2848
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2849 2850
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

2851
    if ((maxvcpus = testConnectGetMaxVcpus(domain->conn, NULL)) < 0)
2852
        return -1;
2853 2854

    if (nrCpus > maxvcpus) {
2855
        virReportError(VIR_ERR_INVALID_ARG,
2856 2857
                       _("requested cpu amount exceeds maximum supported amount "
                         "(%d > %d)"), nrCpus, maxvcpus);
2858 2859
        return -1;
    }
2860

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

2864
    if (virDomainObjGetDefs(privdom, flags, &def, &persistentDef) < 0)
C
Cole Robinson 已提交
2865 2866
        goto cleanup;

2867
    if (def && virDomainDefGetVcpusMax(def) < nrCpus) {
2868 2869
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested cpu amount exceeds maximum (%d > %d)"),
2870
                       nrCpus, virDomainDefGetVcpusMax(def));
2871
        goto cleanup;
2872
    }
2873

2874 2875
    if (persistentDef &&
        !(flags & VIR_DOMAIN_VCPU_MAXIMUM) &&
2876
        virDomainDefGetVcpusMax(persistentDef) < nrCpus) {
2877 2878
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested cpu amount exceeds maximum (%d > %d)"),
2879
                       nrCpus, virDomainDefGetVcpusMax(persistentDef));
2880
        goto cleanup;
2881
    }
2882

2883 2884 2885
    if (def &&
        virDomainDefSetVcpus(def, nrCpus) < 0)
        goto cleanup;
2886

2887 2888
    if (persistentDef) {
        if (flags & VIR_DOMAIN_VCPU_MAXIMUM) {
2889 2890
            if (virDomainDefSetVcpusMax(persistentDef, nrCpus,
                                        driver->xmlopt) < 0)
2891
                goto cleanup;
2892
        } else {
2893 2894
            if (virDomainDefSetVcpus(persistentDef, nrCpus) < 0)
                goto cleanup;
2895
        }
2896
    }
2897

2898 2899
    ret = 0;

2900
 cleanup:
2901
    virDomainObjEndAPI(&privdom);
2902
    return ret;
2903 2904
}

2905 2906 2907

static int
testDomainSetUserPassword(virDomainPtr dom,
J
Ján Tomko 已提交
2908 2909
                          const char *user G_GNUC_UNUSED,
                          const char *password G_GNUC_UNUSED,
2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929
                          unsigned int flags)
{
    int ret = -1;
    virDomainObjPtr vm;

    virCheckFlags(VIR_DOMAIN_PASSWORD_ENCRYPTED, -1);

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

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

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


2930
static int
2931
testDomainSetVcpus(virDomainPtr domain, unsigned int nrCpus)
2932
{
2933
    return testDomainSetVcpusFlags(domain, nrCpus, VIR_DOMAIN_AFFECT_LIVE);
2934 2935
}

C
Cole Robinson 已提交
2936 2937 2938 2939 2940 2941
static int testDomainGetVcpus(virDomainPtr domain,
                              virVcpuInfoPtr info,
                              int maxinfo,
                              unsigned char *cpumaps,
                              int maplen)
{
2942
    testDriverPtr privconn = domain->conn->privateData;
C
Cole Robinson 已提交
2943
    virDomainObjPtr privdom;
2944
    virDomainDefPtr def;
2945
    size_t i;
2946
    int hostcpus;
C
Cole Robinson 已提交
2947 2948
    int ret = -1;
    unsigned long long statbase;
2949
    virBitmapPtr allcpumap = NULL;
C
Cole Robinson 已提交
2950

2951 2952
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
C
Cole Robinson 已提交
2953 2954

    if (!virDomainObjIsActive(privdom)) {
2955
        virReportError(VIR_ERR_OPERATION_INVALID,
2956
                       "%s", _("cannot list vcpus for an inactive domain"));
C
Cole Robinson 已提交
2957 2958 2959
        goto cleanup;
    }

2960
    def = privdom->def;
C
Cole Robinson 已提交
2961

2962
    statbase = g_get_real_time();
C
Cole Robinson 已提交
2963 2964

    hostcpus = VIR_NODEINFO_MAXCPUS(privconn->nodeInfo);
2965 2966 2967 2968 2969
    if (!(allcpumap = virBitmapNew(hostcpus)))
        goto cleanup;

    virBitmapSetAll(allcpumap);

C
Cole Robinson 已提交
2970
    /* Clamp to actual number of vcpus */
2971 2972
    if (maxinfo > virDomainDefGetVcpus(privdom->def))
        maxinfo = virDomainDefGetVcpus(privdom->def);
C
Cole Robinson 已提交
2973

2974 2975
    memset(info, 0, sizeof(*info) * maxinfo);
    memset(cpumaps, 0, maxinfo * maplen);
C
Cole Robinson 已提交
2976

2977
    for (i = 0; i < maxinfo; i++) {
2978
        virDomainVcpuDefPtr vcpu = virDomainDefGetVcpu(def, i);
2979
        virBitmapPtr bitmap = NULL;
C
Cole Robinson 已提交
2980

2981 2982
        if (!vcpu->online)
            continue;
C
Cole Robinson 已提交
2983

2984 2985
        if (vcpu->cpumask)
            bitmap = vcpu->cpumask;
2986 2987 2988 2989
        else if (def->cpumask)
            bitmap = def->cpumask;
        else
            bitmap = allcpumap;
C
Cole Robinson 已提交
2990

2991 2992
        if (cpumaps)
            virBitmapToDataBuf(bitmap, VIR_GET_CPUMAP(cpumaps, maplen, i), maplen);
C
Cole Robinson 已提交
2993

2994 2995 2996
        info[i].number = i;
        info[i].state = VIR_VCPU_RUNNING;
        info[i].cpu = virBitmapLastSetBit(bitmap);
C
Cole Robinson 已提交
2997

2998 2999
        /* Fake an increasing cpu time value */
        info[i].cpuTime = statbase / 10;
C
Cole Robinson 已提交
3000 3001 3002
    }

    ret = maxinfo;
3003
 cleanup:
3004
    virBitmapFree(allcpumap);
3005
    virDomainObjEndAPI(&privdom);
C
Cole Robinson 已提交
3006 3007 3008
    return ret;
}

E
Eric Blake 已提交
3009 3010 3011 3012 3013
static int testDomainPinVcpuFlags(virDomainPtr domain,
                                  unsigned int vcpu,
                                  unsigned char *cpumap,
                                  int maplen,
                                  unsigned int flags)
C
Cole Robinson 已提交
3014
{
3015
    virDomainVcpuDefPtr vcpuinfo;
C
Cole Robinson 已提交
3016
    virDomainObjPtr privdom;
3017
    virDomainDefPtr def;
C
Cole Robinson 已提交
3018 3019
    int ret = -1;

E
Eric Blake 已提交
3020 3021
    virCheckFlags(0, -1);

3022 3023
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
C
Cole Robinson 已提交
3024

3025 3026
    def = privdom->def;

C
Cole Robinson 已提交
3027
    if (!virDomainObjIsActive(privdom)) {
3028
        virReportError(VIR_ERR_OPERATION_INVALID,
3029
                       "%s", _("cannot pin vcpus on an inactive domain"));
C
Cole Robinson 已提交
3030 3031 3032
        goto cleanup;
    }

3033 3034
    if (!(vcpuinfo = virDomainDefGetVcpu(def, vcpu)) ||
        !vcpuinfo->online) {
3035 3036 3037
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested vcpu '%d' is not present in the domain"),
                       vcpu);
C
Cole Robinson 已提交
3038 3039 3040
        goto cleanup;
    }

3041 3042 3043
    virBitmapFree(vcpuinfo->cpumask);

    if (!(vcpuinfo->cpumask = virBitmapNewData(cpumap, maplen)))
3044
        goto cleanup;
C
Cole Robinson 已提交
3045 3046

    ret = 0;
3047

3048
 cleanup:
3049
    virDomainObjEndAPI(&privdom);
C
Cole Robinson 已提交
3050 3051 3052
    return ret;
}

E
Eric Blake 已提交
3053 3054 3055 3056 3057 3058 3059 3060
static int testDomainPinVcpu(virDomainPtr domain,
                             unsigned int vcpu,
                             unsigned char *cpumap,
                             int maplen)
{
    return testDomainPinVcpuFlags(domain, vcpu, cpumap, maplen, 0);
}

3061 3062 3063 3064 3065 3066 3067
static int
testDomainGetVcpuPinInfo(virDomainPtr dom,
                        int ncpumaps,
                        unsigned char *cpumaps,
                        int maplen,
                        unsigned int flags)
{
3068
    testDriverPtr driver = dom->conn->privateData;
3069 3070
    virDomainObjPtr privdom;
    virDomainDefPtr def;
3071
    int ret = -1;
3072 3073 3074 3075 3076 3077 3078

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

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

3079 3080 3081
    ret = virDomainDefGetVcpuPinInfoHelper(def, maplen, ncpumaps, cpumaps,
                                           VIR_NODEINFO_MAXCPUS(driver->nodeInfo),
                                           NULL);
3082 3083 3084 3085 3086 3087

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

3088 3089 3090 3091 3092 3093 3094 3095 3096 3097
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;
3098
    g_autofree char *new_dom_name = NULL;
3099 3100 3101

    virCheckFlags(0, -1);

3102 3103 3104 3105 3106 3107
    if (strchr(new_name, '/')) {
        virReportError(VIR_ERR_XML_ERROR,
                       _("name %s cannot contain '/'"), new_name);
        return -1;
    }

3108
    new_dom_name = g_strdup(new_name);
3109 3110 3111 3112 3113 3114

    event_old = virDomainEventLifecycleNewFromObj(privdom,
                                                  VIR_DOMAIN_EVENT_UNDEFINED,
                                                  VIR_DOMAIN_EVENT_UNDEFINED_RENAMED);

    /* Switch name in domain definition. */
3115
    VIR_FREE(privdom->def->name);
3116
    privdom->def->name = g_steal_pointer(&new_dom_name);
3117 3118 3119 3120 3121 3122

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

3123 3124
    virObjectEventStateQueue(driver->eventState, event_old);
    virObjectEventStateQueue(driver->eventState, event_new);
3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171
    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;
}

3172
static char *testDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
3173
{
3174
    testDriverPtr privconn = domain->conn->privateData;
3175
    virDomainDefPtr def;
3176
    virDomainObjPtr privdom;
3177 3178
    char *ret = NULL;

3179
    virCheckFlags(VIR_DOMAIN_XML_COMMON_FLAGS, NULL);
3180

3181 3182
    if (!(privdom = testDomObjFromDomain(domain)))
        return NULL;
3183

3184 3185
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
3186

3187
    ret = virDomainDefFormat(def, privconn->xmlopt,
3188
                             virDomainDefFormatConvertXMLFlags(flags));
3189

3190
    virDomainObjEndAPI(&privdom);
3191
    return ret;
3192
}
3193

3194 3195 3196 3197 3198 3199

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

3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 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 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283

static int
testDomainSetMemoryParameters(virDomainPtr dom,
                              virTypedParameterPtr params,
                              int nparams,
                              unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    unsigned long long swap_hard_limit = 0;
    unsigned long long hard_limit = 0;
    unsigned long long soft_limit = 0;
    bool set_swap_hard_limit = false;
    bool set_hard_limit = false;
    bool set_soft_limit = false;
    int rc;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_MEMORY_HARD_LIMIT,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_MEMORY_SOFT_LIMIT,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT,
                               VIR_TYPED_PARAM_ULLONG,
                               NULL) < 0)
        return -1;

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

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

#define VIR_GET_LIMIT_PARAMETER(PARAM, VALUE) \
    if ((rc = virTypedParamsGetULLong(params, nparams, PARAM, &VALUE)) < 0) \
        goto cleanup; \
 \
    if (rc == 1) \
        set_ ## VALUE = true;

    VIR_GET_LIMIT_PARAMETER(VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT, swap_hard_limit)
    VIR_GET_LIMIT_PARAMETER(VIR_DOMAIN_MEMORY_HARD_LIMIT, hard_limit)
    VIR_GET_LIMIT_PARAMETER(VIR_DOMAIN_MEMORY_SOFT_LIMIT, soft_limit)

#undef VIR_GET_LIMIT_PARAMETER

    if (set_swap_hard_limit || set_hard_limit) {
        unsigned long long mem_limit = vm->def->mem.hard_limit;
        unsigned long long swap_limit = vm->def->mem.swap_hard_limit;

        if (set_swap_hard_limit)
            swap_limit = swap_hard_limit;

        if (set_hard_limit)
            mem_limit = hard_limit;

        if (mem_limit > swap_limit) {
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("memory hard_limit tunable value must be lower "
                             "than or equal to swap_hard_limit"));
            goto cleanup;
        }
    }

    if (set_soft_limit)
        def->mem.soft_limit = soft_limit;

    if (set_hard_limit)
        def->mem.hard_limit = hard_limit;

    if (set_swap_hard_limit)
        def->mem.swap_hard_limit = swap_hard_limit;

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


3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320
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;
}
3321 3322


3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403
static int
testDomainSetNumaParameters(virDomainPtr dom,
                            virTypedParameterPtr params,
                            int nparams,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    virBitmapPtr nodeset = NULL;
    virDomainNumatuneMemMode config_mode;
    bool live;
    size_t i;
    int mode = -1;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_NUMA_MODE,
                               VIR_TYPED_PARAM_INT,
                               VIR_DOMAIN_NUMA_NODESET,
                               VIR_TYPED_PARAM_STRING,
                               NULL) < 0)
        return -1;

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

    if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
        goto cleanup;

    for (i = 0; i < nparams; i++) {
        virTypedParameterPtr param = &params[i];

        if (STREQ(param->field, VIR_DOMAIN_NUMA_MODE)) {
            mode = param->value.i;

            if (mode < 0 || mode >= VIR_DOMAIN_NUMATUNE_MEM_LAST) {
                virReportError(VIR_ERR_INVALID_ARG,
                               _("unsupported numatune mode: '%d'"), mode);
                goto cleanup;
            }

        } else if (STREQ(param->field, VIR_DOMAIN_NUMA_NODESET)) {
            if (virBitmapParse(param->value.s, &nodeset,
                               VIR_DOMAIN_CPUMASK_LEN) < 0)
                goto cleanup;

            if (virBitmapIsAllClear(nodeset)) {
                virReportError(VIR_ERR_OPERATION_INVALID,
                               _("Invalid nodeset of 'numatune': %s"),
                               param->value.s);
                goto cleanup;
            }
        }
    }

    if (live &&
        mode != -1 &&
        virDomainNumatuneGetMode(def->numa, -1, &config_mode) == 0 &&
        config_mode != mode) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("can't change numatune mode for running domain"));
        goto cleanup;
    }

    if (virDomainNumatuneSet(def->numa,
                             def->placement_mode ==
                             VIR_DOMAIN_CPU_PLACEMENT_MODE_STATIC,
                             -1, mode, nodeset) < 0)
        goto cleanup;

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


3404 3405 3406 3407 3408 3409 3410 3411 3412
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;
3413
    g_autofree char *nodeset = NULL;
3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446
    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;
}
3447 3448


3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 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
static int
testDomainSetInterfaceParameters(virDomainPtr dom,
                                 const char *device,
                                 virTypedParameterPtr params,
                                 int nparams,
                                 unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def;
    virDomainNetDefPtr net = NULL;
    virNetDevBandwidthPtr bandwidth = NULL;
    bool inboundSpecified = false;
    bool outboundSpecified = false;
    size_t i;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_BANDWIDTH_IN_AVERAGE,
                               VIR_TYPED_PARAM_UINT,
                               VIR_DOMAIN_BANDWIDTH_IN_PEAK,
                               VIR_TYPED_PARAM_UINT,
                               VIR_DOMAIN_BANDWIDTH_IN_BURST,
                               VIR_TYPED_PARAM_UINT,
                               VIR_DOMAIN_BANDWIDTH_IN_FLOOR,
                               VIR_TYPED_PARAM_UINT,
                               VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE,
                               VIR_TYPED_PARAM_UINT,
                               VIR_DOMAIN_BANDWIDTH_OUT_PEAK,
                               VIR_TYPED_PARAM_UINT,
                               VIR_DOMAIN_BANDWIDTH_OUT_BURST,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
        return -1;

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

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

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

    if ((VIR_ALLOC(bandwidth) < 0) ||
        (VIR_ALLOC(bandwidth->in) < 0) ||
        (VIR_ALLOC(bandwidth->out) < 0))
        goto cleanup;

    for (i = 0; i < nparams; i++) {
        virTypedParameterPtr param = &params[i];

        if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_AVERAGE)) {
            bandwidth->in->average = param->value.ui;
            inboundSpecified = true;
        } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_PEAK)) {
            bandwidth->in->peak = param->value.ui;
        } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_BURST)) {
            bandwidth->in->burst = param->value.ui;
        } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_FLOOR)) {
            bandwidth->in->floor = param->value.ui;
            inboundSpecified = true;
        } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE)) {
            bandwidth->out->average = param->value.ui;
            outboundSpecified = true;
        } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_OUT_PEAK)) {
            bandwidth->out->peak = param->value.ui;
        } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_OUT_BURST)) {
            bandwidth->out->burst = param->value.ui;
        }
    }

    /* average or floor are mandatory, peak and burst are optional */
    if (!bandwidth->in->average && !bandwidth->in->floor)
        VIR_FREE(bandwidth->in);
    if (!bandwidth->out->average)
        VIR_FREE(bandwidth->out);

    if (!net->bandwidth) {
3530
        net->bandwidth = g_steal_pointer(&bandwidth);
3531 3532 3533
    } else {
        if (bandwidth->in) {
            VIR_FREE(net->bandwidth->in);
3534
            net->bandwidth->in = g_steal_pointer(&bandwidth->in);
3535 3536 3537 3538 3539 3540
        } else if (inboundSpecified) {
            /* if we got here it means user requested @inbound to be cleared */
            VIR_FREE(net->bandwidth->in);
        }
        if (bandwidth->out) {
            VIR_FREE(net->bandwidth->out);
3541
            net->bandwidth->out = g_steal_pointer(&bandwidth->out);
3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555
        } else if (outboundSpecified) {
            /* if we got here it means user requested @outbound to be cleared */
            VIR_FREE(net->bandwidth->out);
        }
    }

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


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
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;
}
3611 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 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692
#define TEST_BLOCK_IOTUNE_MAX 1000000000000000LL

static int
testDomainSetBlockIoTune(virDomainPtr dom,
                         const char *path,
                         virTypedParameterPtr params,
                         int nparams,
                         unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    virDomainBlockIoTuneInfo info = {0};
    virDomainDiskDefPtr conf_disk = NULL;
    virTypedParameterPtr eventParams = NULL;
    int eventNparams = 0;
    int eventMaxparams = 0;
    size_t i;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_BLOCK_IOTUNE_SIZE_IOPS_SEC,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME,
                               VIR_TYPED_PARAM_STRING,
                               VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX_LENGTH,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX_LENGTH,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX_LENGTH,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX_LENGTH,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX_LENGTH,
                               VIR_TYPED_PARAM_ULLONG,
                               VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX_LENGTH,
                               VIR_TYPED_PARAM_ULLONG,
                               NULL) < 0)
        return -1;

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

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

    if (!(conf_disk = virDomainDiskByName(def, path, true))) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("missing persistent configuration for disk '%s'"),
                       path);
        goto cleanup;
    }

    info = conf_disk->blkdeviotune;
3693
    info.group_name = g_strdup(conf_disk->blkdeviotune.group_name);
3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762

    if (virTypedParamsAddString(&eventParams, &eventNparams, &eventMaxparams,
                                VIR_DOMAIN_TUNABLE_BLKDEV_DISK, path) < 0)
        goto cleanup;

#define SET_IOTUNE_FIELD(FIELD, STR, TUNABLE_STR) \
    if (STREQ(param->field, STR)) { \
        info.FIELD = param->value.ul; \
        if (virTypedParamsAddULLong(&eventParams, &eventNparams, \
                                    &eventMaxparams, \
                                    TUNABLE_STR, \
                                    param->value.ul) < 0) \
            goto cleanup; \
        continue; \
    }

    for (i = 0; i < nparams; i++) {
        virTypedParameterPtr param = &params[i];

        if (param->value.ul > TEST_BLOCK_IOTUNE_MAX) {
            virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
                           _("block I/O throttle limit value must"
                             " be no more than %llu"), TEST_BLOCK_IOTUNE_MAX);
            goto cleanup;
        }

        SET_IOTUNE_FIELD(total_bytes_sec,
                         VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC,
                         VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_BYTES_SEC);
        SET_IOTUNE_FIELD(read_bytes_sec,
                         VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC,
                         VIR_DOMAIN_TUNABLE_BLKDEV_READ_BYTES_SEC);
        SET_IOTUNE_FIELD(write_bytes_sec,
                         VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC,
                         VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_BYTES_SEC);
        SET_IOTUNE_FIELD(total_iops_sec,
                         VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC,
                         VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_IOPS_SEC);
        SET_IOTUNE_FIELD(read_iops_sec,
                         VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC,
                         VIR_DOMAIN_TUNABLE_BLKDEV_READ_IOPS_SEC);
        SET_IOTUNE_FIELD(write_iops_sec,
                         VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC,
                         VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_IOPS_SEC);

        SET_IOTUNE_FIELD(total_bytes_sec_max,
                         VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX,
                         VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_BYTES_SEC_MAX);
        SET_IOTUNE_FIELD(read_bytes_sec_max,
                         VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX,
                         VIR_DOMAIN_TUNABLE_BLKDEV_READ_BYTES_SEC_MAX);
        SET_IOTUNE_FIELD(write_bytes_sec_max,
                         VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX,
                         VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_BYTES_SEC_MAX);
        SET_IOTUNE_FIELD(total_iops_sec_max,
                         VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX,
                         VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_IOPS_SEC_MAX);
        SET_IOTUNE_FIELD(read_iops_sec_max,
                         VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX,
                         VIR_DOMAIN_TUNABLE_BLKDEV_READ_IOPS_SEC_MAX);
        SET_IOTUNE_FIELD(write_iops_sec_max,
                         VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX,
                         VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_IOPS_SEC_MAX);
        SET_IOTUNE_FIELD(size_iops_sec,
                         VIR_DOMAIN_BLOCK_IOTUNE_SIZE_IOPS_SEC,
                         VIR_DOMAIN_TUNABLE_BLKDEV_SIZE_IOPS_SEC);

        if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME)) {
            VIR_FREE(info.group_name);
3763
            info.group_name = g_strdup(param->value.s);
3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 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 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859
            if (virTypedParamsAddString(&eventParams,
                                        &eventNparams,
                                        &eventMaxparams,
                                        VIR_DOMAIN_TUNABLE_BLKDEV_GROUP_NAME,
                                        param->value.s) < 0)
                goto cleanup;
            continue;
        }

        SET_IOTUNE_FIELD(total_bytes_sec_max_length,
                         VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX_LENGTH,
                         VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_BYTES_SEC_MAX_LENGTH);
        SET_IOTUNE_FIELD(read_bytes_sec_max_length,
                         VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX_LENGTH,
                         VIR_DOMAIN_TUNABLE_BLKDEV_READ_BYTES_SEC_MAX_LENGTH);
        SET_IOTUNE_FIELD(write_bytes_sec_max_length,
                         VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX_LENGTH,
                         VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_BYTES_SEC_MAX_LENGTH);
        SET_IOTUNE_FIELD(total_iops_sec_max_length,
                         VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX_LENGTH,
                         VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_IOPS_SEC_MAX_LENGTH);
        SET_IOTUNE_FIELD(read_iops_sec_max_length,
                         VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX_LENGTH,
                         VIR_DOMAIN_TUNABLE_BLKDEV_READ_IOPS_SEC_MAX_LENGTH);
        SET_IOTUNE_FIELD(write_iops_sec_max_length,
                         VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX_LENGTH,
                         VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_IOPS_SEC_MAX_LENGTH);
    }
#undef SET_IOTUNE_FIELD

    if ((info.total_bytes_sec && info.read_bytes_sec) ||
        (info.total_bytes_sec && info.write_bytes_sec)) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("total and read/write of bytes_sec "
                         "cannot be set at the same time"));
        goto cleanup;
    }

    if ((info.total_iops_sec && info.read_iops_sec) ||
        (info.total_iops_sec && info.write_iops_sec)) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("total and read/write of iops_sec "
                         "cannot be set at the same time"));
        goto cleanup;
    }

    if ((info.total_bytes_sec_max && info.read_bytes_sec_max) ||
        (info.total_bytes_sec_max && info.write_bytes_sec_max)) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("total and read/write of bytes_sec_max "
                         "cannot be set at the same time"));
        goto cleanup;
    }

    if ((info.total_iops_sec_max && info.read_iops_sec_max) ||
        (info.total_iops_sec_max && info.write_iops_sec_max)) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("total and read/write of iops_sec_max "
                         "cannot be set at the same time"));
        goto cleanup;
    }


#define TEST_BLOCK_IOTUNE_MAX_CHECK(FIELD, FIELD_MAX) \
    do { \
        if (info.FIELD > info.FIELD_MAX) { \
            virReportError(VIR_ERR_INVALID_ARG, \
                           _("%s cannot be set higher than %s "), \
                             #FIELD, #FIELD_MAX); \
            goto cleanup; \
        } \
    } while (0);

    TEST_BLOCK_IOTUNE_MAX_CHECK(total_bytes_sec, total_bytes_sec_max);
    TEST_BLOCK_IOTUNE_MAX_CHECK(read_bytes_sec, read_bytes_sec_max);
    TEST_BLOCK_IOTUNE_MAX_CHECK(write_bytes_sec, write_bytes_sec_max);
    TEST_BLOCK_IOTUNE_MAX_CHECK(total_iops_sec, total_iops_sec_max);
    TEST_BLOCK_IOTUNE_MAX_CHECK(read_iops_sec, read_iops_sec_max);
    TEST_BLOCK_IOTUNE_MAX_CHECK(write_iops_sec, write_iops_sec_max);

#undef TEST_BLOCK_IOTUNE_MAX_CHECK

    if (virDomainDiskSetBlockIOTune(conf_disk, &info) < 0)
        goto cleanup;
    info.group_name = NULL;

    ret = 0;
 cleanup:
    VIR_FREE(info.group_name);
    virDomainObjEndAPI(&vm);
    if (eventNparams)
        virTypedParamsFree(eventParams, eventNparams);
    return ret;
}


3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897
static int
testDomainGetBlockIoTune(virDomainPtr dom,
                         const char *path,
                         virTypedParameterPtr params,
                         int *nparams,
                         unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    virDomainDiskDefPtr disk;
    virDomainBlockIoTuneInfo reply = {0};
    int ret = -1;

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

    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;

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

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

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

    if (!(disk = virDomainDiskByName(def, path, true))) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("disk '%s' was not found in the domain config"),
                       path);
        goto cleanup;
    }

    reply = disk->blkdeviotune;
3898
    reply.group_name = g_strdup(disk->blkdeviotune.group_name);
3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957

    TEST_SET_PARAM(0, VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC,
                   VIR_TYPED_PARAM_ULLONG, reply.total_bytes_sec);
    TEST_SET_PARAM(1, VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC,
                   VIR_TYPED_PARAM_ULLONG, reply.read_bytes_sec);
    TEST_SET_PARAM(2, VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC,
                   VIR_TYPED_PARAM_ULLONG, reply.write_bytes_sec);

    TEST_SET_PARAM(3, VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC,
                   VIR_TYPED_PARAM_ULLONG, reply.total_iops_sec);
    TEST_SET_PARAM(4, VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC,
                   VIR_TYPED_PARAM_ULLONG, reply.read_iops_sec);
    TEST_SET_PARAM(5, VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC,
                   VIR_TYPED_PARAM_ULLONG, reply.write_iops_sec);

    TEST_SET_PARAM(6, VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX,
                   VIR_TYPED_PARAM_ULLONG, reply.total_bytes_sec_max);
    TEST_SET_PARAM(7, VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX,
                   VIR_TYPED_PARAM_ULLONG, reply.read_bytes_sec_max);
    TEST_SET_PARAM(8, VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX,
                   VIR_TYPED_PARAM_ULLONG, reply.write_bytes_sec_max);

    TEST_SET_PARAM(9, VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX,
                   VIR_TYPED_PARAM_ULLONG, reply.total_iops_sec_max);
    TEST_SET_PARAM(10, VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX,
                   VIR_TYPED_PARAM_ULLONG, reply.read_iops_sec_max);
    TEST_SET_PARAM(11, VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX,
                   VIR_TYPED_PARAM_ULLONG, reply.write_iops_sec_max);

    TEST_SET_PARAM(12, VIR_DOMAIN_BLOCK_IOTUNE_SIZE_IOPS_SEC,
                   VIR_TYPED_PARAM_ULLONG, reply.size_iops_sec);

    TEST_SET_PARAM(13, VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME,
                   VIR_TYPED_PARAM_STRING, reply.group_name);
    reply.group_name = NULL;

    TEST_SET_PARAM(14, VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX_LENGTH,
                   VIR_TYPED_PARAM_ULLONG, reply.total_bytes_sec_max_length);
    TEST_SET_PARAM(15, VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX_LENGTH,
                   VIR_TYPED_PARAM_ULLONG, reply.read_bytes_sec_max_length);
    TEST_SET_PARAM(16, VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX_LENGTH,
                   VIR_TYPED_PARAM_ULLONG, reply.write_bytes_sec_max_length);

    TEST_SET_PARAM(17, VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX_LENGTH,
                   VIR_TYPED_PARAM_ULLONG, reply.total_iops_sec_max_length);
    TEST_SET_PARAM(18, VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX_LENGTH,
                   VIR_TYPED_PARAM_ULLONG, reply.read_iops_sec_max_length);
    TEST_SET_PARAM(19, VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX_LENGTH,
                   VIR_TYPED_PARAM_ULLONG, reply.write_iops_sec_max_length);

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

    ret = 0;
 cleanup:
    VIR_FREE(reply.group_name);
    virDomainObjEndAPI(&vm);
    return ret;
}
3958 3959 3960
#undef TEST_SET_PARAM


3961 3962
static int testConnectNumOfDefinedDomains(virConnectPtr conn)
{
3963
    testDriverPtr privconn = conn->privateData;
3964

3965
    return virDomainObjListNumOfDomains(privconn->domains, false, NULL, NULL);
3966 3967
}

3968 3969
static int testConnectListDefinedDomains(virConnectPtr conn,
                                         char **const names,
3970 3971
                                         int maxnames)
{
3972
    testDriverPtr privconn = conn->privateData;
3973 3974

    memset(names, 0, sizeof(*names)*maxnames);
3975 3976
    return virDomainObjListGetInactiveNames(privconn->domains, names, maxnames,
                                            NULL, NULL);
3977 3978
}

3979 3980 3981
static virDomainPtr testDomainDefineXMLFlags(virConnectPtr conn,
                                             const char *xml,
                                             unsigned int flags)
3982
{
3983
    testDriverPtr privconn = conn->privateData;
3984
    virDomainPtr ret = NULL;
3985
    virDomainDefPtr def;
3986
    virDomainObjPtr dom = NULL;
3987
    virObjectEventPtr event = NULL;
3988
    virDomainDefPtr oldDef = NULL;
3989 3990 3991
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;

    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
3992

3993
    if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
3994
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
3995

3996
    if ((def = virDomainDefParseString(xml, privconn->xmlopt,
3997
                                       NULL, parse_flags)) == NULL)
3998
        goto cleanup;
3999

4000 4001 4002
    if (virXMLCheckIllegalChars("name", def->name, "\n") < 0)
        goto cleanup;

4003
    if (testDomainGenerateIfnames(def) < 0)
4004
        goto cleanup;
4005
    if (!(dom = virDomainObjListAdd(privconn->domains,
4006
                                    def,
4007
                                    privconn->xmlopt,
4008 4009
                                    0,
                                    &oldDef)))
4010
        goto cleanup;
4011
    def = NULL;
4012
    dom->persistent = 1;
4013

4014
    event = virDomainEventLifecycleNewFromObj(dom,
4015
                                     VIR_DOMAIN_EVENT_DEFINED,
4016
                                     !oldDef ?
4017 4018
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
4019

4020
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
4021

4022
 cleanup:
4023
    virDomainDefFree(def);
4024
    virDomainDefFree(oldDef);
4025
    virDomainObjEndAPI(&dom);
4026
    virObjectEventStateQueue(privconn->eventState, event);
4027
    return ret;
4028 4029
}

4030 4031 4032 4033 4034 4035
static virDomainPtr
testDomainDefineXML(virConnectPtr conn, const char *xml)
{
    return testDomainDefineXMLFlags(conn, xml, 0);
}

4036 4037 4038 4039 4040 4041
static char *testDomainGetMetadata(virDomainPtr dom,
                                   int type,
                                   const char *uri,
                                   unsigned int flags)
{
    virDomainObjPtr privdom;
4042
    char *ret;
4043 4044 4045 4046

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, NULL);

4047 4048
    if (!(privdom = testDomObjFromDomain(dom)))
        return NULL;
4049

4050
    ret = virDomainObjGetMetadata(privdom, type, uri, flags);
4051

4052
    virDomainObjEndAPI(&privdom);
4053 4054 4055 4056 4057 4058 4059 4060 4061 4062
    return ret;
}

static int testDomainSetMetadata(virDomainPtr dom,
                                 int type,
                                 const char *metadata,
                                 const char *key,
                                 const char *uri,
                                 unsigned int flags)
{
4063
    testDriverPtr privconn = dom->conn->privateData;
4064
    virDomainObjPtr privdom;
4065
    int ret;
4066 4067 4068 4069

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

4070 4071
    if (!(privdom = testDomObjFromDomain(dom)))
        return -1;
4072 4073

    ret = virDomainObjSetMetadata(privdom, type, metadata, key, uri,
4074
                                  privconn->xmlopt,
4075
                                  NULL, NULL, flags);
4076

4077 4078 4079
    if (ret == 0) {
        virObjectEventPtr ev = NULL;
        ev = virDomainEventMetadataChangeNewFromObj(privdom, type, uri);
4080
        virObjectEventStateQueue(privconn->eventState, ev);
4081 4082
    }

4083
    virDomainObjEndAPI(&privdom);
4084 4085 4086
    return ret;
}

4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213
#define TEST_TOTAL_CPUTIME 48772617035LL

static int
testDomainGetDomainTotalCpuStats(virTypedParameterPtr params,
                                 int nparams)
{
    if (nparams == 0) /* return supported number of params */
        return 3;

    if (virTypedParameterAssign(&params[0], VIR_DOMAIN_CPU_STATS_CPUTIME,
                                VIR_TYPED_PARAM_ULLONG, TEST_TOTAL_CPUTIME) < 0)
        return -1;

    if (nparams > 1 &&
        virTypedParameterAssign(&params[1],
                                VIR_DOMAIN_CPU_STATS_USERTIME,
                                VIR_TYPED_PARAM_ULLONG, 5540000000) < 0)
        return -1;

    if (nparams > 2 &&
        virTypedParameterAssign(&params[2],
                                VIR_DOMAIN_CPU_STATS_SYSTEMTIME,
                                VIR_TYPED_PARAM_ULLONG, 6460000000) < 0)
        return -1;

    if (nparams > 3)
        nparams = 3;

    return nparams;
}


static int
testDomainGetPercpuStats(virTypedParameterPtr params,
                         unsigned int nparams,
                         int start_cpu,
                         unsigned int ncpus,
                         int total_cpus)
{
    size_t i;
    int need_cpus;
    int param_idx;
    unsigned long long percpu_time = (TEST_TOTAL_CPUTIME / total_cpus);

    /* return the number of supported params */
    if (nparams == 0 && ncpus != 0)
        return 2;

    /* return total number of cpus */
    if (ncpus == 0)
        return total_cpus;

    if (start_cpu >= total_cpus) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("start_cpu %d larger than maximum of %d"),
                       start_cpu, total_cpus - 1);
        return -1;
    }

    /* return percpu cputime in index 0 */
    param_idx = 0;

    /* number of cpus to compute */
    need_cpus = MIN(total_cpus, start_cpu + ncpus);

    for (i = start_cpu; i < need_cpus; i++) {
        int idx = (i - start_cpu) * nparams + param_idx;

        if (virTypedParameterAssign(&params[idx],
                                    VIR_DOMAIN_CPU_STATS_CPUTIME,
                                    VIR_TYPED_PARAM_ULLONG,
                                    percpu_time + i) < 0)
            return -1;
    }

    /* return percpu vcputime in index 1 */
    param_idx = 1;

    if (param_idx < nparams) {
        for (i = start_cpu; i < need_cpus; i++) {
            int idx = (i - start_cpu) * nparams + param_idx;

            if (virTypedParameterAssign(&params[idx],
                                        VIR_DOMAIN_CPU_STATS_VCPUTIME,
                                        VIR_TYPED_PARAM_ULLONG,
                                        percpu_time + i - 1234567890) < 0)
                return -1;
        }
        param_idx++;
    }

    return param_idx;
}


static int
testDomainGetCPUStats(virDomainPtr dom,
                      virTypedParameterPtr params,
                      unsigned int nparams,
                      int start_cpu,
                      unsigned int ncpus,
                      unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    testDriverPtr privconn = dom->conn->privateData;
    int ret = -1;

    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);

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

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

    if (start_cpu == -1)
        ret = testDomainGetDomainTotalCpuStats(params, nparams);
    else
        ret = testDomainGetPercpuStats(params, nparams, start_cpu, ncpus,
                                       privconn->nodeInfo.cores);

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


4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247
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;
}
4248

4249 4250
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
4251 4252
                                      int startCell, int maxCells)
{
4253
    testDriverPtr privconn = conn->privateData;
4254 4255
    int cell;
    size_t i;
4256
    int ret = -1;
4257

4258
    virObjectLock(privconn);
4259
    if (startCell >= privconn->numCells) {
4260 4261
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("Range exceeds available cells"));
4262
        goto cleanup;
4263 4264
    }

4265 4266 4267 4268
    for (cell = startCell, i = 0;
         (cell < privconn->numCells && i < maxCells);
         ++cell, ++i) {
        freemems[i] = privconn->cells[cell].mem;
4269
    }
4270
    ret = i;
4271

4272
 cleanup:
4273
    virObjectUnlock(privconn);
4274
    return ret;
4275 4276
}

4277 4278 4279
#define TEST_NB_CPU_STATS 4

static int
J
Ján Tomko 已提交
4280 4281
testNodeGetCPUStats(virConnectPtr conn G_GNUC_UNUSED,
                    int cpuNum G_GNUC_UNUSED,
4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322
                    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;
}
4323

4324 4325 4326 4327 4328 4329 4330
static unsigned long long
testNodeGetFreeMemory(virConnectPtr conn)
{
    testDriverPtr privconn = conn->privateData;
    unsigned int freeMem = 0;
    size_t i;

4331
    virObjectLock(privconn);
4332 4333 4334 4335

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

4336
    virObjectUnlock(privconn);
4337 4338 4339
    return freeMem;
}

4340
static int
J
Ján Tomko 已提交
4341
testNodeGetFreePages(virConnectPtr conn G_GNUC_UNUSED,
4342
                     unsigned int npages,
J
Ján Tomko 已提交
4343 4344
                     unsigned int *pages G_GNUC_UNUSED,
                     int startCell G_GNUC_UNUSED,
4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363
                     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;
}

4364 4365
static int testDomainCreateWithFlags(virDomainPtr domain, unsigned int flags)
{
4366
    testDriverPtr privconn = domain->conn->privateData;
4367
    virDomainObjPtr privdom;
4368
    virObjectEventPtr event = NULL;
4369
    int ret = -1;
4370

4371 4372
    virCheckFlags(0, -1);

4373
    virObjectLock(privconn);
4374

4375
    if (!(privdom = testDomObjFromDomain(domain)))
4376
        goto cleanup;
4377

J
Jiri Denemark 已提交
4378
    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_SHUTOFF) {
4379 4380
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Domain '%s' is already running"), domain->name);
4381
        goto cleanup;
4382 4383
    }

4384
    if (testDomainStartState(privconn, privdom,
J
Jiri Denemark 已提交
4385
                             VIR_DOMAIN_RUNNING_BOOTED) < 0)
4386 4387 4388
        goto cleanup;
    domain->id = privdom->def->id;

4389
    event = virDomainEventLifecycleNewFromObj(privdom,
4390 4391
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
4392
    ret = 0;
4393

4394
 cleanup:
4395
    virDomainObjEndAPI(&privdom);
4396
    virObjectEventStateQueue(privconn->eventState, event);
4397
    virObjectUnlock(privconn);
4398
    return ret;
4399 4400
}

4401 4402
static int testDomainCreate(virDomainPtr domain)
{
4403 4404 4405
    return testDomainCreateWithFlags(domain, 0);
}

4406 4407

static int testDomainCreateWithFiles(virDomainPtr domain,
J
Ján Tomko 已提交
4408 4409
                                     unsigned int nfiles G_GNUC_UNUSED,
                                     int *files G_GNUC_UNUSED,
4410 4411 4412 4413 4414 4415
                                     unsigned int flags)
{
    return testDomainCreateWithFlags(domain, flags);
}


4416 4417 4418
static int testDomainUndefineFlags(virDomainPtr domain,
                                   unsigned int flags)
{
4419
    testDriverPtr privconn = domain->conn->privateData;
4420
    virDomainObjPtr privdom;
4421
    virObjectEventPtr event = NULL;
4422
    int nsnapshots;
4423
    int ret = -1;
4424

4425 4426
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
                  VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
4427

4428

4429
    if (!(privdom = testDomObjFromDomain(domain)))
4430
        goto cleanup;
4431

C
Cole Robinson 已提交
4432 4433 4434 4435 4436 4437 4438 4439
    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;
    }

4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457
    /* 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. */
    }

4458
    event = virDomainEventLifecycleNewFromObj(privdom,
4459 4460
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
C
Cole Robinson 已提交
4461 4462
    privdom->hasManagedSave = false;

4463
    if (virDomainObjIsActive(privdom))
4464
        privdom->persistent = 0;
4465
    else
4466
        virDomainObjListRemove(privconn->domains, privdom);
4467

4468
    ret = 0;
4469

4470
 cleanup:
4471
    virDomainObjEndAPI(&privdom);
4472
    virObjectEventStateQueue(privconn->eventState, event);
4473
    return ret;
4474 4475
}

4476 4477 4478 4479 4480
static int testDomainUndefine(virDomainPtr domain)
{
    return testDomainUndefineFlags(domain, 0);
}

4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541

static int
testDomainFSFreeze(virDomainPtr dom,
                   const char **mountpoints,
                   unsigned int nmountpoints,
                   unsigned int flags)
{
    virDomainObjPtr vm;
    testDomainObjPrivatePtr priv;
    size_t i;
    int ret = -1;

    virCheckFlags(0, -1);

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

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

    priv = vm->privateData;

    if (nmountpoints == 0) {
        ret = 2 - (priv->frozen[0] + priv->frozen[1]);
        priv->frozen[0] = priv->frozen[1] = true;
    } else {
        int nfreeze = 0;
        bool freeze[2];

        memcpy(&freeze, priv->frozen, 2);

        for (i = 0; i < nmountpoints; i++) {
            if (STREQ(mountpoints[i], "/")) {
                if (!freeze[0]) {
                    freeze[0] = true;
                    nfreeze++;
                }
            } else if (STREQ(mountpoints[i], "/boot")) {
                if (!freeze[1]) {
                    freeze[1] = true;
                    nfreeze++;
                }
            } else {
                virReportError(VIR_ERR_OPERATION_INVALID,
                               _("mount point not found: %s"),
                               mountpoints[i]);
                goto cleanup;
            }
        }

        /* steal the helper copy */
        memcpy(priv->frozen, &freeze, 2);
        ret = nfreeze;
    }

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


4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601
static int
testDomainFSThaw(virDomainPtr dom,
                   const char **mountpoints,
                   unsigned int nmountpoints,
                   unsigned int flags)
{
    virDomainObjPtr vm;
    testDomainObjPrivatePtr priv;
    size_t i;
    int ret = -1;

    virCheckFlags(0, -1);

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

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

    priv = vm->privateData;

    if (nmountpoints == 0) {
        ret = priv->frozen[0] + priv->frozen[1];
        priv->frozen[0] = priv->frozen[1] = false;
    } else {
        int nthaw = 0;
        bool freeze[2];

        memcpy(&freeze, priv->frozen, 2);

        for (i = 0; i < nmountpoints; i++) {
            if (STREQ(mountpoints[i], "/")) {
                if (freeze[0]) {
                    freeze[0] = false;
                    nthaw++;
                }
            } else if (STREQ(mountpoints[i], "/boot")) {
                if (freeze[1]) {
                    freeze[1] = false;
                    nthaw++;
                }
            } else {
                virReportError(VIR_ERR_OPERATION_INVALID,
                               _("mount point not found: %s"),
                               mountpoints[i]);
                goto cleanup;
            }
        }

        /* steal the helper copy */
        memcpy(priv->frozen, &freeze, 2);
        ret = nthaw;
    }

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


4602 4603 4604
static int
testDomainFSTrim(virDomainPtr dom,
                 const char *mountPoint,
J
Ján Tomko 已提交
4605
                 unsigned long long minimum G_GNUC_UNUSED,
4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632
                 unsigned int flags)
{
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(0, -1);

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

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

    if (mountPoint && STRNEQ(mountPoint, "/") && STRNEQ(mountPoint, "/boot")) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("mount point not found: %s"),
                       mountPoint);
        goto cleanup;
    }

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


4633 4634 4635
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
4636 4637
    virDomainObjPtr privdom;

4638 4639
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
4640

4641
    *autostart = privdom->autostart;
4642

4643
    virDomainObjEndAPI(&privdom);
4644
    return 0;
4645 4646 4647 4648 4649 4650
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
4651 4652
    virDomainObjPtr privdom;

4653 4654
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
4655

4656
    privdom->autostart = autostart ? 1 : 0;
4657

4658
    virDomainObjEndAPI(&privdom);
4659
    return 0;
4660
}
4661

4662 4663 4664 4665 4666 4667 4668 4669
static int testDomainGetDiskErrors(virDomainPtr dom,
                                   virDomainDiskErrorPtr errors,
                                   unsigned int maxerrors,
                                   unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;
    size_t i;
4670
    size_t nerrors = 0;
4671 4672 4673 4674

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(dom)))
4675
        return -1;
4676 4677 4678 4679

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

4680 4681
    nerrors = MIN(vm->def->ndisks, maxerrors);

4682
    if (errors) {
4683 4684 4685 4686
        /* sanitize input */
        memset(errors, 0, sizeof(virDomainDiskError) * nerrors);

        for (i = 0; i < nerrors; i++) {
4687
            errors[i].disk = g_strdup(vm->def->disks[i]->dst);
4688
            errors[i].error = (i % (VIR_DOMAIN_DISK_ERROR_LAST - 1)) + 1;
4689 4690 4691 4692 4693 4694 4695 4696
        }
        ret = i;
    } else {
        ret = vm->def->ndisks;
    }

 cleanup:
    if (ret < 0) {
4697
        for (i = 0; i < nerrors; i++)
4698 4699
            VIR_FREE(errors[i].disk);
    }
4700
    virDomainObjEndAPI(&vm);
4701 4702 4703
    return ret;
}

4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733


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 ||
4734 4735 4736 4737 4738 4739
                VIR_ALLOC(info_ret[0]->devAlias) < 0)
                goto cleanup;

            info_ret[0]->mountpoint = g_strdup("/");
            info_ret[0]->fstype = g_strdup("ext4");
            info_ret[0]->devAlias[0] = g_strdup(name);
4740
            info_ret[0]->name = g_strdup_printf("%s1", name);
4741 4742

            if (VIR_ALLOC(info_ret[1]) < 0 ||
4743 4744 4745 4746 4747 4748
                VIR_ALLOC(info_ret[1]->devAlias) < 0)
                goto cleanup;

            info_ret[1]->mountpoint = g_strdup("/boot");
            info_ret[1]->fstype = g_strdup("ext4");
            info_ret[1]->devAlias[0] = g_strdup(name);
4749
            info_ret[1]->name = g_strdup_printf("%s2", name);
4750 4751 4752

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

4753
            *info = g_steal_pointer(&info_ret);
4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773

            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;
}


4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836
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;
}


4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867
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;
    }

4868
    *params = g_steal_pointer(&par);
4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879
    *nparams = npar;
    npar = 0;

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


J
Ján Tomko 已提交
4880
static char *testDomainGetSchedulerType(virDomainPtr domain G_GNUC_UNUSED,
4881 4882
                                        int *nparams)
{
4883 4884 4885
    if (nparams)
        *nparams = 1;

M
Michal Privoznik 已提交
4886
    return g_strdup("fair");
4887 4888
}

4889
static int
4890 4891 4892 4893
testDomainGetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int *nparams,
                                      unsigned int flags)
4894
{
4895
    virDomainObjPtr privdom;
4896
    int ret = -1;
4897

4898 4899
    virCheckFlags(0, -1);

4900 4901
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
4902

4903 4904
    if (virTypedParameterAssign(params, VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, 50) < 0)
4905
        goto cleanup;
4906 4907
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
4908 4909

    *nparams = 1;
4910 4911
    ret = 0;

4912
 cleanup:
4913
    virDomainObjEndAPI(&privdom);
4914
    return ret;
4915
}
4916

4917
static int
4918 4919 4920
testDomainGetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int *nparams)
4921
{
4922
    return testDomainGetSchedulerParametersFlags(domain, params, nparams, 0);
4923
}
4924

4925
static int
4926 4927 4928 4929
testDomainSetSchedulerParametersFlags(virDomainPtr domain,
                                      virTypedParameterPtr params,
                                      int nparams,
                                      unsigned int flags)
4930
{
4931
    virDomainObjPtr privdom;
4932 4933
    int ret = -1;
    size_t i;
4934

4935
    virCheckFlags(0, -1);
4936 4937 4938 4939
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
4940
        return -1;
4941

4942 4943
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
4944

4945
    for (i = 0; i < nparams; i++) {
4946 4947 4948
        if (STREQ(params[i].field, VIR_DOMAIN_SCHEDULER_WEIGHT)) {
            /* XXX */
            /*privdom->weight = params[i].value.ui;*/
4949
        }
4950
    }
4951

4952 4953
    ret = 0;

4954
    virDomainObjEndAPI(&privdom);
4955
    return ret;
4956 4957
}

4958
static int
4959 4960 4961
testDomainSetSchedulerParameters(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int nparams)
4962
{
4963
    return testDomainSetSchedulerParametersFlags(domain, params, nparams, 0);
4964 4965
}

4966 4967
static int testDomainBlockStats(virDomainPtr domain,
                                const char *path,
4968
                                virDomainBlockStatsPtr stats)
4969 4970 4971
{
    virDomainObjPtr privdom;
    unsigned long long statbase;
4972
    int ret = -1;
4973

4974 4975 4976 4977 4978 4979
    if (!*path) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("summary statistics are not supported yet"));
        return ret;
    }

4980 4981
    if (!(privdom = testDomObjFromDomain(domain)))
        return ret;
4982

4983
    if (virDomainObjCheckActive(privdom) < 0)
4984 4985
        goto error;

4986
    if (virDomainDiskIndexByName(privdom->def, path, false) < 0) {
4987 4988
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path: %s"), path);
4989 4990 4991
        goto error;
    }

J
Ján Tomko 已提交
4992
    /* No significance to these numbers, just enough to mix it up */
4993
    statbase = g_get_real_time();
4994 4995 4996 4997
    stats->rd_req = statbase / 10;
    stats->rd_bytes = statbase / 20;
    stats->wr_req = statbase / 30;
    stats->wr_bytes = statbase / 40;
4998
    stats->errs = statbase / (1000LL * 1000LL * 2);
4999 5000

    ret = 0;
5001
 error:
5002
    virDomainObjEndAPI(&privdom);
5003 5004 5005
    return ret;
}

5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050

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;
}


5051 5052 5053
static int
testDomainInterfaceAddresses(virDomainPtr dom,
                             virDomainInterfacePtr **ifaces,
5054
                             unsigned int source,
5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066
                             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);

5067 5068 5069 5070 5071 5072 5073
    if (source >= VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LAST) {
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
                       _("Unknown IP address data source %d"),
                       source);
        return -1;
    }

5074 5075 5076 5077 5078 5079 5080 5081 5082 5083
    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++) {
5084 5085
        const virDomainNetDef *net = vm->def->nets[i];

5086 5087 5088
        if (VIR_ALLOC(iface) < 0)
            goto cleanup;

5089
        iface->name = g_strdup(net->ifname);
5090

5091
        virMacAddrFormat(&net->mac, macaddr);
5092
        iface->hwaddr = g_strdup(macaddr);
5093 5094 5095

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

5098 5099 5100
        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;
5101

5102 5103 5104 5105 5106 5107
            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;
5108
            iface->addrs[0].addr = g_strdup_printf("192.168.0.%zu", 1 + i);
5109 5110

        }
5111 5112 5113 5114

        VIR_APPEND_ELEMENT_INPLACE(ifaces_ret, ifaces_count, iface);
    }

5115
    *ifaces = g_steal_pointer(&ifaces_ret);
5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130
    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;
}

5131 5132 5133 5134
static int
testDomainInterfaceStats(virDomainPtr domain,
                         const char *device,
                         virDomainInterfaceStatsPtr stats)
5135 5136 5137
{
    virDomainObjPtr privdom;
    unsigned long long statbase;
M
Michal Privoznik 已提交
5138 5139 5140
    virDomainNetDefPtr net = NULL;
    int ret = -1;

5141

5142 5143
    if (!(privdom = testDomObjFromDomain(domain)))
        return -1;
5144

5145
    if (virDomainObjCheckActive(privdom) < 0)
5146 5147
        goto error;

5148
    if (!(net = virDomainNetFind(privdom->def, device)))
5149 5150
        goto error;

J
Ján Tomko 已提交
5151
    /* No significance to these numbers, just enough to mix it up */
5152
    statbase = g_get_real_time();
5153 5154
    stats->rx_bytes = statbase / 10;
    stats->rx_packets = statbase / 100;
5155 5156
    stats->rx_errs = statbase / (1000LL * 1000LL * 1);
    stats->rx_drop = statbase / (1000LL * 1000LL * 2);
5157 5158
    stats->tx_bytes = statbase / 20;
    stats->tx_packets = statbase / 110;
5159 5160
    stats->tx_errs = statbase / (1000LL * 1000LL * 3);
    stats->tx_drop = statbase / (1000LL * 1000LL * 4);
5161 5162

    ret = 0;
5163
 error:
5164
    virDomainObjEndAPI(&privdom);
5165 5166 5167
    return ret;
}

5168

5169 5170 5171 5172
static virNetworkObjPtr
testNetworkObjFindByUUID(testDriverPtr privconn,
                         const unsigned char *uuid)
{
5173
    virNetworkObjPtr obj;
5174 5175
    char uuidstr[VIR_UUID_STRING_BUFLEN];

5176
    if (!(obj = virNetworkObjFindByUUID(privconn->networks, uuid))) {
5177 5178 5179 5180 5181 5182
        virUUIDFormat(uuid, uuidstr);
        virReportError(VIR_ERR_NO_NETWORK,
                       _("no network with matching uuid '%s'"),
                       uuidstr);
    }

5183
    return obj;
5184 5185 5186
}


5187 5188 5189
static virNetworkPtr
testNetworkLookupByUUID(virConnectPtr conn,
                        const unsigned char *uuid)
5190
{
5191
    testDriverPtr privconn = conn->privateData;
5192
    virNetworkObjPtr obj;
5193
    virNetworkDefPtr def;
5194
    virNetworkPtr net = NULL;
5195

5196
    if (!(obj = testNetworkObjFindByUUID(privconn, uuid)))
5197
        goto cleanup;
5198
    def = virNetworkObjGetDef(obj);
5199

5200
    net = virGetNetwork(conn, def->name, def->uuid);
5201

5202
 cleanup:
5203 5204
    virNetworkObjEndAPI(&obj);
    return net;
5205
}
5206

5207 5208 5209 5210 5211

static virNetworkObjPtr
testNetworkObjFindByName(testDriverPtr privconn,
                         const char *name)
{
5212
    virNetworkObjPtr obj;
5213

5214
    if (!(obj = virNetworkObjFindByName(privconn->networks, name)))
5215 5216 5217 5218
        virReportError(VIR_ERR_NO_NETWORK,
                       _("no network with matching name '%s'"),
                       name);

5219
    return obj;
5220 5221 5222
}


5223 5224 5225
static virNetworkPtr
testNetworkLookupByName(virConnectPtr conn,
                        const char *name)
5226
{
5227
    testDriverPtr privconn = conn->privateData;
5228
    virNetworkObjPtr obj;
5229
    virNetworkDefPtr def;
5230
    virNetworkPtr net = NULL;
5231

5232
    if (!(obj = testNetworkObjFindByName(privconn, name)))
5233
        goto cleanup;
5234
    def = virNetworkObjGetDef(obj);
5235

5236
    net = virGetNetwork(conn, def->name, def->uuid);
5237

5238
 cleanup:
5239 5240
    virNetworkObjEndAPI(&obj);
    return net;
5241 5242 5243
}


5244 5245
static int
testConnectNumOfNetworks(virConnectPtr conn)
5246
{
5247
    testDriverPtr privconn = conn->privateData;
M
Michal Privoznik 已提交
5248 5249
    return virNetworkObjListNumOfNetworks(privconn->networks, true, NULL,
                                          conn);
5250 5251
}

5252 5253 5254 5255

static int
testConnectListNetworks(virConnectPtr conn,
                        char **const names,
5256
                        int maxnames)
5257
{
5258
    testDriverPtr privconn = conn->privateData;
M
Michal Privoznik 已提交
5259 5260
    return virNetworkObjListGetNames(privconn->networks, true, names,
                                     maxnames, NULL, conn);
5261 5262
}

5263 5264 5265

static int
testConnectNumOfDefinedNetworks(virConnectPtr conn)
5266
{
5267
    testDriverPtr privconn = conn->privateData;
M
Michal Privoznik 已提交
5268 5269
    return virNetworkObjListNumOfNetworks(privconn->networks, false, NULL,
                                          conn);
5270 5271
}

5272 5273 5274 5275

static int
testConnectListDefinedNetworks(virConnectPtr conn,
                               char **const names,
5276
                               int maxnames)
5277
{
5278
    testDriverPtr privconn = conn->privateData;
M
Michal Privoznik 已提交
5279 5280
    return virNetworkObjListGetNames(privconn->networks, false, names,
                                     maxnames, NULL, conn);
5281 5282
}

5283

5284
static int
5285
testConnectListAllNetworks(virConnectPtr conn,
5286 5287 5288
                           virNetworkPtr **nets,
                           unsigned int flags)
{
5289
    testDriverPtr privconn = conn->privateData;
5290 5291 5292

    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);

5293
    return virNetworkObjListExport(conn, privconn->networks, nets, NULL, flags);
5294
}
5295

5296 5297 5298

static int
testNetworkIsActive(virNetworkPtr net)
5299
{
5300
    testDriverPtr privconn = net->conn->privateData;
5301 5302 5303
    virNetworkObjPtr obj;
    int ret = -1;

5304
    if (!(obj = testNetworkObjFindByUUID(privconn, net->uuid)))
5305
        goto cleanup;
5306

5307 5308
    ret = virNetworkObjIsActive(obj);

5309
 cleanup:
5310
    virNetworkObjEndAPI(&obj);
5311 5312 5313
    return ret;
}

5314 5315 5316

static int
testNetworkIsPersistent(virNetworkPtr net)
5317
{
5318
    testDriverPtr privconn = net->conn->privateData;
5319 5320 5321
    virNetworkObjPtr obj;
    int ret = -1;

5322
    if (!(obj = testNetworkObjFindByUUID(privconn, net->uuid)))
5323
        goto cleanup;
5324

5325
    ret = virNetworkObjIsPersistent(obj);
5326

5327
 cleanup:
5328
    virNetworkObjEndAPI(&obj);
5329 5330 5331 5332
    return ret;
}


5333 5334
static virNetworkPtr
testNetworkCreateXML(virConnectPtr conn, const char *xml)
5335
{
5336
    testDriverPtr privconn = conn->privateData;
5337
    virNetworkDefPtr newDef;
5338
    virNetworkObjPtr obj = NULL;
5339
    virNetworkDefPtr def;
5340
    virNetworkPtr net = NULL;
5341
    virObjectEventPtr event = NULL;
5342

5343
    if ((newDef = virNetworkDefParseString(xml, NULL)) == NULL)
5344
        goto cleanup;
5345

5346
    if (!(obj = virNetworkObjAssignDef(privconn->networks, newDef,
5347 5348
                                       VIR_NETWORK_OBJ_LIST_ADD_LIVE |
                                       VIR_NETWORK_OBJ_LIST_ADD_CHECK_LIVE)))
5349
        goto cleanup;
5350 5351
    newDef = NULL;
    def = virNetworkObjGetDef(obj);
5352
    virNetworkObjSetActive(obj, true);
5353

5354
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
5355 5356
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
5357

5358
    net = virGetNetwork(conn, def->name, def->uuid);
5359

5360
 cleanup:
5361
    virNetworkDefFree(newDef);
5362
    virObjectEventStateQueue(privconn->eventState, event);
5363 5364
    virNetworkObjEndAPI(&obj);
    return net;
5365 5366
}

5367 5368 5369 5370

static virNetworkPtr
testNetworkDefineXML(virConnectPtr conn,
                     const char *xml)
5371
{
5372
    testDriverPtr privconn = conn->privateData;
5373
    virNetworkDefPtr newDef;
5374
    virNetworkObjPtr obj = NULL;
5375
    virNetworkDefPtr def;
5376
    virNetworkPtr net = NULL;
5377
    virObjectEventPtr event = NULL;
5378

5379
    if ((newDef = virNetworkDefParseString(xml, NULL)) == NULL)
5380
        goto cleanup;
5381

5382
    if (!(obj = virNetworkObjAssignDef(privconn->networks, newDef, 0)))
5383
        goto cleanup;
5384 5385
    newDef = NULL;
    def = virNetworkObjGetDef(obj);
5386

5387
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
5388 5389
                                        VIR_NETWORK_EVENT_DEFINED,
                                        0);
5390

5391
    net = virGetNetwork(conn, def->name, def->uuid);
5392

5393
 cleanup:
5394
    virNetworkDefFree(newDef);
5395
    virObjectEventStateQueue(privconn->eventState, event);
5396 5397
    virNetworkObjEndAPI(&obj);
    return net;
5398 5399
}

5400 5401

static int
5402
testNetworkUndefine(virNetworkPtr net)
5403
{
5404 5405
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
5406
    int ret = -1;
5407
    virObjectEventPtr event = NULL;
5408

5409
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
5410
        goto cleanup;
5411

5412
    if (virNetworkObjIsActive(obj)) {
5413
        virReportError(VIR_ERR_OPERATION_INVALID,
5414
                       _("Network '%s' is still running"), net->name);
5415
        goto cleanup;
5416 5417
    }

5418
    event = virNetworkEventLifecycleNew(net->name, net->uuid,
5419 5420
                                        VIR_NETWORK_EVENT_UNDEFINED,
                                        0);
5421

5422
    virNetworkObjRemoveInactive(privconn->networks, obj);
5423
    ret = 0;
5424

5425
 cleanup:
5426
    virObjectEventStateQueue(privconn->eventState, event);
5427
    virNetworkObjEndAPI(&obj);
5428
    return ret;
5429 5430
}

5431

5432 5433 5434 5435 5436 5437 5438 5439
static int
testNetworkUpdate(virNetworkPtr net,
                  unsigned int command,
                  unsigned int section,
                  int parentIndex,
                  const char *xml,
                  unsigned int flags)
{
5440
    testDriverPtr privconn = net->conn->privateData;
5441
    virNetworkObjPtr obj = NULL;
5442 5443 5444 5445 5446 5447
    int isActive, ret = -1;

    virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
                  VIR_NETWORK_UPDATE_AFFECT_CONFIG,
                  -1);

5448
    if (!(obj = testNetworkObjFindByUUID(privconn, net->uuid)))
5449 5450 5451 5452 5453
        goto cleanup;

    /* VIR_NETWORK_UPDATE_AFFECT_CURRENT means "change LIVE if network
     * is active, else change CONFIG
    */
5454
    isActive = virNetworkObjIsActive(obj);
5455 5456 5457 5458 5459 5460 5461 5462 5463 5464
    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 */
5465 5466
    if (virNetworkObjUpdate(obj, command, section,
                            parentIndex, xml, NULL, flags) < 0)
5467 5468 5469
       goto cleanup;

    ret = 0;
5470
 cleanup:
5471
    virNetworkObjEndAPI(&obj);
5472 5473 5474
    return ret;
}

5475 5476

static int
5477
testNetworkCreate(virNetworkPtr net)
5478
{
5479 5480
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
5481
    virNetworkDefPtr def;
5482
    int ret = -1;
5483
    virObjectEventPtr event = NULL;
5484

5485
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
5486
        goto cleanup;
5487
    def = virNetworkObjGetDef(obj);
5488

5489
    if (virNetworkObjIsActive(obj)) {
5490
        virReportError(VIR_ERR_OPERATION_INVALID,
5491
                       _("Network '%s' is already running"), net->name);
5492
        goto cleanup;
5493 5494
    }

5495
    virNetworkObjSetActive(obj, true);
5496
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
5497 5498
                                        VIR_NETWORK_EVENT_STARTED,
                                        0);
5499
    ret = 0;
5500

5501
 cleanup:
5502
    virObjectEventStateQueue(privconn->eventState, event);
5503
    virNetworkObjEndAPI(&obj);
5504
    return ret;
5505 5506
}

5507 5508

static int
5509
testNetworkDestroy(virNetworkPtr net)
5510
{
5511 5512
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
5513
    virNetworkDefPtr def;
5514
    int ret = -1;
5515
    virObjectEventPtr event = NULL;
5516

5517
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
5518
        goto cleanup;
5519
    def = virNetworkObjGetDef(obj);
5520

5521
    virNetworkObjSetActive(obj, false);
5522
    event = virNetworkEventLifecycleNew(def->name, def->uuid,
5523 5524
                                        VIR_NETWORK_EVENT_STOPPED,
                                        0);
5525
    if (!virNetworkObjIsPersistent(obj))
5526
        virNetworkObjRemoveInactive(privconn->networks, obj);
5527

5528 5529
    ret = 0;

5530
 cleanup:
5531
    virObjectEventStateQueue(privconn->eventState, event);
5532
    virNetworkObjEndAPI(&obj);
5533
    return ret;
5534 5535
}

5536 5537

static char *
5538
testNetworkGetXMLDesc(virNetworkPtr net,
5539
                      unsigned int flags)
5540
{
5541 5542
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
5543
    char *ret = NULL;
5544

E
Eric Blake 已提交
5545 5546
    virCheckFlags(0, NULL);

5547
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
5548
        goto cleanup;
5549

5550
    ret = virNetworkDefFormat(virNetworkObjGetDef(obj), NULL, flags);
5551

5552
 cleanup:
5553
    virNetworkObjEndAPI(&obj);
5554
    return ret;
5555 5556
}

5557 5558

static char *
5559
testNetworkGetBridgeName(virNetworkPtr net)
5560
{
5561
    testDriverPtr privconn = net->conn->privateData;
5562
    char *bridge = NULL;
5563
    virNetworkObjPtr obj;
5564
    virNetworkDefPtr def;
5565

5566
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
5567
        goto cleanup;
5568
    def = virNetworkObjGetDef(obj);
5569

5570
    if (!(def->bridge)) {
5571 5572
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("network '%s' does not have a bridge name."),
5573
                       def->name);
5574 5575 5576
        goto cleanup;
    }

5577
    bridge = g_strdup(def->bridge);
5578

5579
 cleanup:
5580
    virNetworkObjEndAPI(&obj);
5581 5582 5583
    return bridge;
}

5584 5585

static int
5586
testNetworkGetAutostart(virNetworkPtr net,
5587
                        int *autostart)
5588
{
5589 5590
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
5591
    int ret = -1;
5592

5593
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
5594
        goto cleanup;
5595

5596
    *autostart = virNetworkObjIsAutostart(obj) ? 1 : 0;
5597 5598
    ret = 0;

5599
 cleanup:
5600
    virNetworkObjEndAPI(&obj);
5601
    return ret;
5602 5603
}

5604 5605

static int
5606
testNetworkSetAutostart(virNetworkPtr net,
5607
                        int autostart)
5608
{
5609 5610
    testDriverPtr privconn = net->conn->privateData;
    virNetworkObjPtr obj;
5611
    bool new_autostart = (autostart != 0);
5612
    int ret = -1;
5613

5614
    if (!(obj = testNetworkObjFindByName(privconn, net->name)))
5615
        goto cleanup;
5616

5617 5618
    virNetworkObjSetAutostart(obj, new_autostart);

5619 5620
    ret = 0;

5621
 cleanup:
5622
    virNetworkObjEndAPI(&obj);
5623
    return ret;
5624
}
5625

C
Cole Robinson 已提交
5626

L
Laine Stump 已提交
5627 5628 5629 5630 5631
/*
 * Physical host interface routines
 */


5632 5633 5634 5635
static virInterfaceObjPtr
testInterfaceObjFindByName(testDriverPtr privconn,
                           const char *name)
{
5636
    virInterfaceObjPtr obj;
5637

5638
    virObjectLock(privconn);
5639
    obj = virInterfaceObjListFindByName(privconn->ifaces, name);
5640
    virObjectUnlock(privconn);
5641

5642
    if (!obj)
5643 5644 5645 5646
        virReportError(VIR_ERR_NO_INTERFACE,
                       _("no interface with matching name '%s'"),
                       name);

5647
    return obj;
5648 5649 5650
}


5651 5652
static int
testConnectNumOfInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
5653
{
5654
    testDriverPtr privconn = conn->privateData;
5655
    int ninterfaces;
L
Laine Stump 已提交
5656

5657
    virObjectLock(privconn);
5658
    ninterfaces = virInterfaceObjListNumOfInterfaces(privconn->ifaces, true);
5659
    virObjectUnlock(privconn);
5660
    return ninterfaces;
L
Laine Stump 已提交
5661 5662
}

5663 5664 5665 5666 5667

static int
testConnectListInterfaces(virConnectPtr conn,
                          char **const names,
                          int maxnames)
L
Laine Stump 已提交
5668
{
5669
    testDriverPtr privconn = conn->privateData;
5670
    int nnames;
L
Laine Stump 已提交
5671

5672
    virObjectLock(privconn);
5673 5674
    nnames = virInterfaceObjListGetNames(privconn->ifaces, true,
                                         names, maxnames);
5675
    virObjectUnlock(privconn);
L
Laine Stump 已提交
5676

5677
    return nnames;
L
Laine Stump 已提交
5678 5679
}

5680 5681 5682

static int
testConnectNumOfDefinedInterfaces(virConnectPtr conn)
L
Laine Stump 已提交
5683
{
5684
    testDriverPtr privconn = conn->privateData;
5685
    int ninterfaces;
L
Laine Stump 已提交
5686

5687
    virObjectLock(privconn);
5688
    ninterfaces = virInterfaceObjListNumOfInterfaces(privconn->ifaces, false);
5689
    virObjectUnlock(privconn);
5690
    return ninterfaces;
L
Laine Stump 已提交
5691 5692
}

5693 5694 5695 5696 5697

static int
testConnectListDefinedInterfaces(virConnectPtr conn,
                                 char **const names,
                                 int maxnames)
L
Laine Stump 已提交
5698
{
5699
    testDriverPtr privconn = conn->privateData;
5700
    int nnames;
L
Laine Stump 已提交
5701

5702
    virObjectLock(privconn);
5703 5704
    nnames = virInterfaceObjListGetNames(privconn->ifaces, false,
                                         names, maxnames);
5705
    virObjectUnlock(privconn);
L
Laine Stump 已提交
5706

5707
    return nnames;
L
Laine Stump 已提交
5708 5709
}

5710

5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724
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);
}


5725 5726 5727
static virInterfacePtr
testInterfaceLookupByName(virConnectPtr conn,
                          const char *name)
L
Laine Stump 已提交
5728
{
5729
    testDriverPtr privconn = conn->privateData;
5730
    virInterfaceObjPtr obj;
5731
    virInterfaceDefPtr def;
L
Laine Stump 已提交
5732 5733
    virInterfacePtr ret = NULL;

5734
    if (!(obj = testInterfaceObjFindByName(privconn, name)))
5735
        return NULL;
5736
    def = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
5737

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

5740
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
5741 5742 5743
    return ret;
}

5744 5745 5746 5747

static virInterfacePtr
testInterfaceLookupByMACString(virConnectPtr conn,
                               const char *mac)
L
Laine Stump 已提交
5748
{
5749
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
5750
    int ifacect;
5751
    char *ifacenames[] = { NULL, NULL };
L
Laine Stump 已提交
5752 5753
    virInterfacePtr ret = NULL;

5754
    virObjectLock(privconn);
5755 5756
    ifacect = virInterfaceObjListFindByMACString(privconn->ifaces, mac,
                                                 ifacenames, 2);
5757
    virObjectUnlock(privconn);
L
Laine Stump 已提交
5758 5759

    if (ifacect == 0) {
5760 5761
        virReportError(VIR_ERR_NO_INTERFACE,
                       _("no interface with matching mac '%s'"), mac);
L
Laine Stump 已提交
5762 5763 5764 5765
        goto cleanup;
    }

    if (ifacect > 1) {
5766
        virReportError(VIR_ERR_MULTIPLE_INTERFACES, NULL);
L
Laine Stump 已提交
5767 5768 5769
        goto cleanup;
    }

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

5772
 cleanup:
5773 5774
    VIR_FREE(ifacenames[0]);
    VIR_FREE(ifacenames[1]);
L
Laine Stump 已提交
5775 5776 5777
    return ret;
}

5778 5779 5780

static int
testInterfaceIsActive(virInterfacePtr iface)
5781
{
5782
    testDriverPtr privconn = iface->conn->privateData;
5783 5784 5785
    virInterfaceObjPtr obj;
    int ret = -1;

5786
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
5787
        return -1;
5788

5789 5790
    ret = virInterfaceObjIsActive(obj);

5791
    virInterfaceObjEndAPI(&obj);
5792 5793 5794
    return ret;
}

5795 5796 5797 5798

static int
testInterfaceChangeBegin(virConnectPtr conn,
                         unsigned int flags)
5799
{
5800
    testDriverPtr privconn = conn->privateData;
5801 5802
    int ret = -1;

E
Eric Blake 已提交
5803 5804
    virCheckFlags(0, -1);

5805
    virObjectLock(privconn);
5806
    if (privconn->transaction_running) {
5807
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
5808
                       _("there is another transaction running."));
5809 5810 5811 5812 5813
        goto cleanup;
    }

    privconn->transaction_running = true;

5814
    if (!(privconn->backupIfaces = virInterfaceObjListClone(privconn->ifaces)))
5815 5816 5817
        goto cleanup;

    ret = 0;
5818
 cleanup:
5819
    virObjectUnlock(privconn);
5820 5821 5822
    return ret;
}

5823 5824 5825 5826

static int
testInterfaceChangeCommit(virConnectPtr conn,
                          unsigned int flags)
5827
{
5828
    testDriverPtr privconn = conn->privateData;
5829 5830
    int ret = -1;

E
Eric Blake 已提交
5831 5832
    virCheckFlags(0, -1);

5833
    virObjectLock(privconn);
5834 5835

    if (!privconn->transaction_running) {
5836
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
5837 5838
                       _("no transaction running, "
                         "nothing to be committed."));
5839 5840 5841
        goto cleanup;
    }

5842
    virObjectUnref(privconn->backupIfaces);
5843 5844 5845 5846
    privconn->transaction_running = false;

    ret = 0;

5847
 cleanup:
5848
    virObjectUnlock(privconn);
5849 5850 5851 5852

    return ret;
}

5853 5854 5855 5856

static int
testInterfaceChangeRollback(virConnectPtr conn,
                            unsigned int flags)
5857
{
5858
    testDriverPtr privconn = conn->privateData;
5859 5860
    int ret = -1;

E
Eric Blake 已提交
5861 5862
    virCheckFlags(0, -1);

5863
    virObjectLock(privconn);
5864 5865

    if (!privconn->transaction_running) {
5866
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
5867 5868
                       _("no transaction running, "
                         "nothing to rollback."));
5869 5870 5871
        goto cleanup;
    }

5872
    virObjectUnref(privconn->ifaces);
5873 5874
    privconn->ifaces = privconn->backupIfaces;
    privconn->backupIfaces = NULL;
5875 5876 5877 5878 5879

    privconn->transaction_running = false;

    ret = 0;

5880
 cleanup:
5881
    virObjectUnlock(privconn);
5882 5883
    return ret;
}
5884

5885 5886 5887 5888

static char *
testInterfaceGetXMLDesc(virInterfacePtr iface,
                        unsigned int flags)
L
Laine Stump 已提交
5889
{
5890
    testDriverPtr privconn = iface->conn->privateData;
5891
    virInterfaceObjPtr obj;
5892
    virInterfaceDefPtr def;
L
Laine Stump 已提交
5893 5894
    char *ret = NULL;

E
Eric Blake 已提交
5895 5896
    virCheckFlags(0, NULL);

5897
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
5898
        return NULL;
5899
    def = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
5900

5901
    ret = virInterfaceDefFormat(def);
L
Laine Stump 已提交
5902

5903
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
5904 5905 5906 5907
    return ret;
}


5908 5909 5910 5911
static virInterfacePtr
testInterfaceDefineXML(virConnectPtr conn,
                       const char *xmlStr,
                       unsigned int flags)
L
Laine Stump 已提交
5912
{
5913
    testDriverPtr privconn = conn->privateData;
L
Laine Stump 已提交
5914
    virInterfaceDefPtr def;
5915
    virInterfaceObjPtr obj = NULL;
5916
    virInterfaceDefPtr objdef;
L
Laine Stump 已提交
5917 5918
    virInterfacePtr ret = NULL;

E
Eric Blake 已提交
5919 5920
    virCheckFlags(0, NULL);

5921
    virObjectLock(privconn);
5922
    if ((def = virInterfaceDefParseString(xmlStr)) == NULL)
L
Laine Stump 已提交
5923 5924
        goto cleanup;

5925
    if ((obj = virInterfaceObjListAssignDef(privconn->ifaces, def)) == NULL)
L
Laine Stump 已提交
5926 5927
        goto cleanup;
    def = NULL;
5928
    objdef = virInterfaceObjGetDef(obj);
L
Laine Stump 已提交
5929

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

5932
 cleanup:
L
Laine Stump 已提交
5933
    virInterfaceDefFree(def);
5934
    virInterfaceObjEndAPI(&obj);
5935
    virObjectUnlock(privconn);
L
Laine Stump 已提交
5936 5937 5938
    return ret;
}

5939 5940 5941

static int
testInterfaceUndefine(virInterfacePtr iface)
L
Laine Stump 已提交
5942
{
5943
    testDriverPtr privconn = iface->conn->privateData;
5944
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
5945

5946
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
5947
        return -1;
L
Laine Stump 已提交
5948

5949
    virInterfaceObjListRemove(privconn->ifaces, obj);
5950
    virObjectUnref(obj);
L
Laine Stump 已提交
5951

5952
    return 0;
L
Laine Stump 已提交
5953 5954
}

5955 5956 5957 5958

static int
testInterfaceCreate(virInterfacePtr iface,
                    unsigned int flags)
L
Laine Stump 已提交
5959
{
5960
    testDriverPtr privconn = iface->conn->privateData;
5961
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
5962 5963
    int ret = -1;

E
Eric Blake 已提交
5964 5965
    virCheckFlags(0, -1);

5966
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
5967
        return -1;
L
Laine Stump 已提交
5968

5969
    if (virInterfaceObjIsActive(obj)) {
5970
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
5971 5972 5973
        goto cleanup;
    }

5974
    virInterfaceObjSetActive(obj, true);
L
Laine Stump 已提交
5975 5976
    ret = 0;

5977
 cleanup:
5978
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
5979 5980 5981
    return ret;
}

5982 5983 5984 5985

static int
testInterfaceDestroy(virInterfacePtr iface,
                     unsigned int flags)
L
Laine Stump 已提交
5986
{
5987
    testDriverPtr privconn = iface->conn->privateData;
5988
    virInterfaceObjPtr obj;
L
Laine Stump 已提交
5989 5990
    int ret = -1;

E
Eric Blake 已提交
5991 5992
    virCheckFlags(0, -1);

5993
    if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
5994
        return -1;
L
Laine Stump 已提交
5995

5996
    if (!virInterfaceObjIsActive(obj)) {
5997
        virReportError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
5998 5999 6000
        goto cleanup;
    }

6001
    virInterfaceObjSetActive(obj, false);
L
Laine Stump 已提交
6002 6003
    ret = 0;

6004
 cleanup:
6005
    virInterfaceObjEndAPI(&obj);
L
Laine Stump 已提交
6006 6007 6008 6009 6010
    return ret;
}



C
Cole Robinson 已提交
6011 6012 6013 6014
/*
 * Storage Driver routines
 */

6015
static int
6016
testStoragePoolObjSetDefaults(virStoragePoolObjPtr obj)
6017
{
6018
    char *configFile;
6019
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
6020

6021 6022 6023
    def->capacity = defaultPoolCap;
    def->allocation = defaultPoolAlloc;
    def->available = defaultPoolCap - defaultPoolAlloc;
C
Cole Robinson 已提交
6024

6025
    configFile = g_strdup("");
6026 6027 6028

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

6031

6032 6033 6034 6035
static virStoragePoolObjPtr
testStoragePoolObjFindByName(testDriverPtr privconn,
                             const char *name)
{
6036
    virStoragePoolObjPtr obj;
6037

6038
    virObjectLock(privconn);
6039
    obj = virStoragePoolObjFindByName(privconn->pools, name);
6040
    virObjectUnlock(privconn);
6041

6042
    if (!obj)
6043 6044 6045 6046
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       name);

6047
    return obj;
6048 6049 6050
}


6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062
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);
6063
        virStoragePoolObjEndAPI(&obj);
6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082
        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);
6083
        virStoragePoolObjEndAPI(&obj);
6084 6085 6086 6087 6088 6089 6090
        return NULL;
    }

    return obj;
}


6091 6092 6093 6094
static virStoragePoolObjPtr
testStoragePoolObjFindByUUID(testDriverPtr privconn,
                             const unsigned char *uuid)
{
6095
    virStoragePoolObjPtr obj;
6096 6097
    char uuidstr[VIR_UUID_STRING_BUFLEN];

6098
    virObjectLock(privconn);
6099
    obj = virStoragePoolObjFindByUUID(privconn->pools, uuid);
6100
    virObjectUnlock(privconn);
6101

6102
    if (!obj) {
6103 6104 6105 6106 6107 6108
        virUUIDFormat(uuid, uuidstr);
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching uuid '%s'"),
                       uuidstr);
    }

6109
    return obj;
6110 6111 6112
}


C
Cole Robinson 已提交
6113 6114
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
6115 6116
                            const unsigned char *uuid)
{
6117
    testDriverPtr privconn = conn->privateData;
6118
    virStoragePoolObjPtr obj;
6119
    virStoragePoolDefPtr def;
6120
    virStoragePoolPtr pool = NULL;
C
Cole Robinson 已提交
6121

6122
    if (!(obj = testStoragePoolObjFindByUUID(privconn, uuid)))
6123
        return NULL;
6124
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
6125

6126
    pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
6127

6128
    virStoragePoolObjEndAPI(&obj);
6129
    return pool;
C
Cole Robinson 已提交
6130 6131
}

6132

C
Cole Robinson 已提交
6133 6134
static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
6135 6136
                            const char *name)
{
6137
    testDriverPtr privconn = conn->privateData;
6138
    virStoragePoolObjPtr obj;
6139
    virStoragePoolDefPtr def;
6140
    virStoragePoolPtr pool = NULL;
C
Cole Robinson 已提交
6141

6142
    if (!(obj = testStoragePoolObjFindByName(privconn, name)))
6143
        return NULL;
6144
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
6145

6146
    pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
6147

6148
    virStoragePoolObjEndAPI(&obj);
6149
    return pool;
C
Cole Robinson 已提交
6150 6151
}

6152

C
Cole Robinson 已提交
6153
static virStoragePoolPtr
6154 6155
testStoragePoolLookupByVolume(virStorageVolPtr vol)
{
C
Cole Robinson 已提交
6156 6157 6158
    return testStoragePoolLookupByName(vol->conn, vol->pool);
}

6159

C
Cole Robinson 已提交
6160
static int
6161 6162
testConnectNumOfStoragePools(virConnectPtr conn)
{
6163
    testDriverPtr privconn = conn->privateData;
6164
    int numActive = 0;
C
Cole Robinson 已提交
6165

6166
    virObjectLock(privconn);
6167
    numActive = virStoragePoolObjNumOfStoragePools(privconn->pools, conn,
6168
                                                   true, NULL);
6169
    virObjectUnlock(privconn);
C
Cole Robinson 已提交
6170 6171 6172 6173

    return numActive;
}

6174

C
Cole Robinson 已提交
6175
static int
6176 6177
testConnectListStoragePools(virConnectPtr conn,
                            char **const names,
6178
                            int maxnames)
6179
{
6180
    testDriverPtr privconn = conn->privateData;
6181
    int n = 0;
C
Cole Robinson 已提交
6182

6183
    virObjectLock(privconn);
6184
    n = virStoragePoolObjGetNames(privconn->pools, conn, true, NULL,
6185
                                  names, maxnames);
6186
    virObjectUnlock(privconn);
C
Cole Robinson 已提交
6187 6188 6189 6190

    return n;
}

6191

C
Cole Robinson 已提交
6192
static int
6193 6194
testConnectNumOfDefinedStoragePools(virConnectPtr conn)
{
6195
    testDriverPtr privconn = conn->privateData;
6196
    int numInactive = 0;
C
Cole Robinson 已提交
6197

6198
    virObjectLock(privconn);
6199
    numInactive = virStoragePoolObjNumOfStoragePools(privconn->pools, conn,
6200
                                                     false, NULL);
6201
    virObjectUnlock(privconn);
C
Cole Robinson 已提交
6202 6203 6204 6205

    return numInactive;
}

6206

C
Cole Robinson 已提交
6207
static int
6208 6209
testConnectListDefinedStoragePools(virConnectPtr conn,
                                   char **const names,
6210
                                   int maxnames)
6211
{
6212
    testDriverPtr privconn = conn->privateData;
6213
    int n = 0;
C
Cole Robinson 已提交
6214

6215
    virObjectLock(privconn);
6216
    n = virStoragePoolObjGetNames(privconn->pools, conn, false, NULL,
6217
                                  names, maxnames);
6218
    virObjectUnlock(privconn);
C
Cole Robinson 已提交
6219 6220 6221 6222

    return n;
}

6223

6224
static int
6225 6226 6227
testConnectListAllStoragePools(virConnectPtr conn,
                               virStoragePoolPtr **pools,
                               unsigned int flags)
6228
{
6229
    testDriverPtr privconn = conn->privateData;
6230 6231 6232 6233
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

6234
    virObjectLock(privconn);
6235
    ret = virStoragePoolObjListExport(conn, privconn->pools, pools,
6236
                                      NULL, flags);
6237
    virObjectUnlock(privconn);
6238 6239 6240

    return ret;
}
C
Cole Robinson 已提交
6241

6242 6243 6244

static int
testStoragePoolIsActive(virStoragePoolPtr pool)
6245
{
6246
    testDriverPtr privconn = pool->conn->privateData;
6247 6248 6249
    virStoragePoolObjPtr obj;
    int ret = -1;

6250
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
6251
        goto cleanup;
6252

6253 6254
    ret = virStoragePoolObjIsActive(obj);

6255
 cleanup:
6256
    if (obj)
6257
        virStoragePoolObjEndAPI(&obj);
6258 6259 6260
    return ret;
}

6261 6262 6263

static int
testStoragePoolIsPersistent(virStoragePoolPtr pool)
6264
{
6265
    testDriverPtr privconn = pool->conn->privateData;
6266 6267 6268
    virStoragePoolObjPtr obj;
    int ret = -1;

6269
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
6270
        return -1;
6271

6272
    ret = virStoragePoolObjGetConfigFile(obj) ? 1 : 0;
6273

6274
    virStoragePoolObjEndAPI(&obj);
6275 6276 6277 6278
    return ret;
}


C
Cole Robinson 已提交
6279
static int
6280 6281
testStoragePoolCreate(virStoragePoolPtr pool,
                      unsigned int flags)
E
Eric Blake 已提交
6282
{
6283
    testDriverPtr privconn = pool->conn->privateData;
6284
    virStoragePoolObjPtr obj;
6285
    virObjectEventPtr event = NULL;
6286

E
Eric Blake 已提交
6287 6288
    virCheckFlags(0, -1);

6289 6290
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
6291

6292
    virStoragePoolObjSetActive(obj, true);
6293 6294 6295 6296

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

6298
    virObjectEventStateQueue(privconn->eventState, event);
6299
    virStoragePoolObjEndAPI(&obj);
6300
    return 0;
C
Cole Robinson 已提交
6301 6302
}

6303

C
Cole Robinson 已提交
6304
static char *
J
Ján Tomko 已提交
6305
testConnectFindStoragePoolSources(virConnectPtr conn G_GNUC_UNUSED,
6306 6307 6308
                                  const char *type,
                                  const char *srcSpec,
                                  unsigned int flags)
C
Cole Robinson 已提交
6309
{
6310 6311
    int pool_type;
    char *ret = NULL;
J
Ján Tomko 已提交
6312
    g_autoptr(virStoragePoolSource) source = NULL;
6313

E
Eric Blake 已提交
6314 6315
    virCheckFlags(0, NULL);

6316 6317
    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
6318 6319
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
6320
        return NULL;
6321 6322 6323
    }

    if (srcSpec) {
6324
        source = virStoragePoolDefParseSourceString(srcSpec, pool_type);
6325
        if (!source)
6326
            return NULL;
6327 6328 6329 6330 6331
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
6332
        ret = g_strdup(defaultPoolSourcesLogicalXML);
6333
        return ret;
6334 6335

    case VIR_STORAGE_POOL_NETFS:
6336
        if (!source || !source->hosts[0].name) {
6337 6338
            virReportError(VIR_ERR_INVALID_ARG,
                           "%s", _("hostname must be specified for netfs sources"));
6339
            return NULL;
6340 6341
        }

6342
        ret = g_strdup_printf(defaultPoolSourcesNetFSXML, source->hosts[0].name);
6343
        return ret;
6344 6345

    default:
6346 6347
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source discovery"), type);
6348 6349
    }

6350
    return NULL;
C
Cole Robinson 已提交
6351 6352 6353
}


6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375
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;
6376
    virNodeDeviceObjEndAPI(&obj);
6377 6378 6379 6380 6381

    return 0;
}


C
Cole Robinson 已提交
6382
static virStoragePoolPtr
6383 6384 6385
testStoragePoolCreateXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
6386
{
6387
    testDriverPtr privconn = conn->privateData;
6388
    virStoragePoolObjPtr obj = NULL;
6389
    virStoragePoolDefPtr def;
6390
    virStoragePoolPtr pool = NULL;
6391
    virObjectEventPtr event = NULL;
J
Ján Tomko 已提交
6392
    g_autoptr(virStoragePoolDef) newDef = NULL;
C
Cole Robinson 已提交
6393

E
Eric Blake 已提交
6394 6395
    virCheckFlags(0, NULL);

6396
    virObjectLock(privconn);
6397
    if (!(newDef = virStoragePoolDefParseString(xml)))
6398
        goto cleanup;
C
Cole Robinson 已提交
6399

6400 6401
    if (!(obj = virStoragePoolObjListAdd(privconn->pools, newDef,
                                         VIR_STORAGE_POOL_OBJ_LIST_ADD_CHECK_LIVE)))
6402
        goto cleanup;
6403 6404
    newDef = NULL;
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
6405

6406
    if (def->source.adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
6407 6408 6409 6410 6411
        /* 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,
6412 6413
                            def->source.adapter.data.fchost.wwnn,
                            def->source.adapter.data.fchost.wwpn) < 0) {
6414
            virStoragePoolObjRemove(privconn->pools, obj);
6415 6416 6417 6418
            goto cleanup;
        }
    }

6419
    if (testStoragePoolObjSetDefaults(obj) == -1) {
6420
        virStoragePoolObjRemove(privconn->pools, obj);
6421
        goto cleanup;
C
Cole Robinson 已提交
6422
    }
6423 6424 6425 6426

    /* *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 */
6427
    virStoragePoolObjSetConfigFile(obj, NULL);
6428

6429
    virStoragePoolObjSetActive(obj, true);
C
Cole Robinson 已提交
6430

6431
    event = virStoragePoolEventLifecycleNew(def->name, def->uuid,
6432 6433 6434
                                            VIR_STORAGE_POOL_EVENT_STARTED,
                                            0);

6435
    pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
6436

6437
 cleanup:
6438
    virObjectEventStateQueue(privconn->eventState, event);
6439
    virStoragePoolObjEndAPI(&obj);
6440
    virObjectUnlock(privconn);
6441
    return pool;
C
Cole Robinson 已提交
6442 6443
}

6444

C
Cole Robinson 已提交
6445
static virStoragePoolPtr
6446 6447 6448
testStoragePoolDefineXML(virConnectPtr conn,
                         const char *xml,
                         unsigned int flags)
E
Eric Blake 已提交
6449
{
6450
    testDriverPtr privconn = conn->privateData;
6451
    virStoragePoolObjPtr obj = NULL;
6452
    virStoragePoolDefPtr def;
6453
    virStoragePoolPtr pool = NULL;
6454
    virObjectEventPtr event = NULL;
J
Ján Tomko 已提交
6455
    g_autoptr(virStoragePoolDef) newDef = NULL;
C
Cole Robinson 已提交
6456

E
Eric Blake 已提交
6457 6458
    virCheckFlags(0, NULL);

6459
    virObjectLock(privconn);
6460
    if (!(newDef = virStoragePoolDefParseString(xml)))
6461
        goto cleanup;
C
Cole Robinson 已提交
6462

6463 6464 6465
    newDef->capacity = defaultPoolCap;
    newDef->allocation = defaultPoolAlloc;
    newDef->available = defaultPoolCap - defaultPoolAlloc;
C
Cole Robinson 已提交
6466

6467
    if (!(obj = virStoragePoolObjListAdd(privconn->pools, newDef, 0)))
6468
        goto cleanup;
6469 6470
    newDef = NULL;
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
6471

6472
    event = virStoragePoolEventLifecycleNew(def->name, def->uuid,
6473 6474 6475
                                            VIR_STORAGE_POOL_EVENT_DEFINED,
                                            0);

6476
    if (testStoragePoolObjSetDefaults(obj) == -1) {
6477
        virStoragePoolObjRemove(privconn->pools, obj);
6478
        goto cleanup;
C
Cole Robinson 已提交
6479 6480
    }

6481
    pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
6482

6483
 cleanup:
6484
    virObjectEventStateQueue(privconn->eventState, event);
6485
    virStoragePoolObjEndAPI(&obj);
6486
    virObjectUnlock(privconn);
6487
    return pool;
C
Cole Robinson 已提交
6488 6489
}

6490

C
Cole Robinson 已提交
6491
static int
6492 6493
testStoragePoolUndefine(virStoragePoolPtr pool)
{
6494
    testDriverPtr privconn = pool->conn->privateData;
6495
    virStoragePoolObjPtr obj;
6496
    virObjectEventPtr event = NULL;
6497

6498 6499
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
6500

6501 6502 6503 6504
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_UNDEFINED,
                                            0);

6505
    virStoragePoolObjRemove(privconn->pools, obj);
6506
    virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
6507

6508
    virObjectEventStateQueue(privconn->eventState, event);
6509
    return 0;
C
Cole Robinson 已提交
6510 6511
}

6512

C
Cole Robinson 已提交
6513
static int
6514
testStoragePoolBuild(virStoragePoolPtr pool,
E
Eric Blake 已提交
6515 6516
                     unsigned int flags)
{
6517
    testDriverPtr privconn = pool->conn->privateData;
6518
    virStoragePoolObjPtr obj;
6519
    virObjectEventPtr event = NULL;
6520

E
Eric Blake 已提交
6521 6522
    virCheckFlags(0, -1);

6523 6524
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
6525

6526 6527 6528 6529
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_CREATED,
                                            0);

6530
    virStoragePoolObjEndAPI(&obj);
6531

6532
    virObjectEventStateQueue(privconn->eventState, event);
6533
    return 0;
C
Cole Robinson 已提交
6534 6535 6536
}


6537 6538
static int
testDestroyVport(testDriverPtr privconn,
J
Ján Tomko 已提交
6539 6540
                 const char *wwnn G_GNUC_UNUSED,
                 const char *wwpn G_GNUC_UNUSED)
6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551
{
    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 */
6552 6553
    if (!(obj = virNodeDeviceObjListFindByName(privconn->devs,
                                               "scsi_host12"))) {
6554 6555
        virReportError(VIR_ERR_NO_NODE_DEVICE, "%s",
                       _("no node device with matching name 'scsi_host12'"));
6556
        return -1;
6557 6558 6559 6560 6561 6562
    }

    event = virNodeDeviceEventLifecycleNew("scsi_host12",
                                           VIR_NODE_DEVICE_EVENT_DELETED,
                                           0);

6563
    virNodeDeviceObjListRemove(privconn->devs, obj);
6564
    virObjectUnref(obj);
6565

6566
    virObjectEventStateQueue(privconn->eventState, event);
6567
    return 0;
6568 6569 6570
}


C
Cole Robinson 已提交
6571
static int
6572 6573
testStoragePoolDestroy(virStoragePoolPtr pool)
{
6574
    testDriverPtr privconn = pool->conn->privateData;
6575
    virStoragePoolObjPtr obj;
6576
    virStoragePoolDefPtr def;
6577
    int ret = -1;
6578
    virObjectEventPtr event = NULL;
6579

6580
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
6581
        return -1;
6582
    def = virStoragePoolObjGetDef(obj);
6583

6584
    virStoragePoolObjSetActive(obj, false);
6585

6586
    if (def->source.adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
6587
        if (testDestroyVport(privconn,
6588 6589
                             def->source.adapter.data.fchost.wwnn,
                             def->source.adapter.data.fchost.wwpn) < 0)
6590 6591 6592
            goto cleanup;
    }

6593 6594
    event = virStoragePoolEventLifecycleNew(def->name,
                                            def->uuid,
6595 6596
                                            VIR_STORAGE_POOL_EVENT_STOPPED,
                                            0);
C
Cole Robinson 已提交
6597

6598
    if (!(virStoragePoolObjGetConfigFile(obj)))
6599
        virStoragePoolObjRemove(privconn->pools, obj);
6600

6601
    ret = 0;
C
Cole Robinson 已提交
6602

6603
 cleanup:
6604
    virObjectEventStateQueue(privconn->eventState, event);
6605
    virStoragePoolObjEndAPI(&obj);
6606
    return ret;
C
Cole Robinson 已提交
6607 6608 6609 6610
}


static int
6611
testStoragePoolDelete(virStoragePoolPtr pool,
E
Eric Blake 已提交
6612 6613
                      unsigned int flags)
{
6614
    testDriverPtr privconn = pool->conn->privateData;
6615
    virStoragePoolObjPtr obj;
6616
    virObjectEventPtr event = NULL;
6617

E
Eric Blake 已提交
6618 6619
    virCheckFlags(0, -1);

6620 6621
    if (!(obj = testStoragePoolObjFindInactiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
6622

6623 6624 6625 6626
    event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid,
                                            VIR_STORAGE_POOL_EVENT_DELETED,
                                            0);

6627
    virObjectEventStateQueue(privconn->eventState, event);
6628

6629
    virStoragePoolObjEndAPI(&obj);
6630
    return 0;
C
Cole Robinson 已提交
6631 6632 6633 6634
}


static int
6635
testStoragePoolRefresh(virStoragePoolPtr pool,
E
Eric Blake 已提交
6636 6637
                       unsigned int flags)
{
6638
    testDriverPtr privconn = pool->conn->privateData;
6639
    virStoragePoolObjPtr obj;
6640
    virObjectEventPtr event = NULL;
6641

E
Eric Blake 已提交
6642 6643
    virCheckFlags(0, -1);

6644 6645
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return -1;
6646

6647
    event = virStoragePoolEventRefreshNew(pool->name, pool->uuid);
C
Cole Robinson 已提交
6648

6649
    virObjectEventStateQueue(privconn->eventState, event);
6650
    virStoragePoolObjEndAPI(&obj);
6651
    return 0;
C
Cole Robinson 已提交
6652 6653 6654 6655
}


static int
6656
testStoragePoolGetInfo(virStoragePoolPtr pool,
6657 6658
                       virStoragePoolInfoPtr info)
{
6659
    testDriverPtr privconn = pool->conn->privateData;
6660
    virStoragePoolObjPtr obj;
6661
    virStoragePoolDefPtr def;
6662

6663
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
6664
        return -1;
6665
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
6666 6667

    memset(info, 0, sizeof(virStoragePoolInfo));
6668
    if (virStoragePoolObjIsActive(obj))
C
Cole Robinson 已提交
6669 6670 6671
        info->state = VIR_STORAGE_POOL_RUNNING;
    else
        info->state = VIR_STORAGE_POOL_INACTIVE;
6672 6673 6674
    info->capacity = def->capacity;
    info->allocation = def->allocation;
    info->available = def->available;
C
Cole Robinson 已提交
6675

6676
    virStoragePoolObjEndAPI(&obj);
6677
    return 0;
C
Cole Robinson 已提交
6678 6679
}

6680

C
Cole Robinson 已提交
6681
static char *
6682
testStoragePoolGetXMLDesc(virStoragePoolPtr pool,
E
Eric Blake 已提交
6683 6684
                          unsigned int flags)
{
6685
    testDriverPtr privconn = pool->conn->privateData;
6686
    virStoragePoolObjPtr obj;
6687
    char *ret = NULL;
6688

E
Eric Blake 已提交
6689 6690
    virCheckFlags(0, NULL);

6691
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
6692
        return NULL;
6693

6694
    ret = virStoragePoolDefFormat(virStoragePoolObjGetDef(obj));
6695

6696
    virStoragePoolObjEndAPI(&obj);
6697
    return ret;
C
Cole Robinson 已提交
6698 6699
}

6700

C
Cole Robinson 已提交
6701
static int
6702
testStoragePoolGetAutostart(virStoragePoolPtr pool,
6703 6704
                            int *autostart)
{
6705
    testDriverPtr privconn = pool->conn->privateData;
6706
    virStoragePoolObjPtr obj;
6707

6708
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
6709
        return -1;
C
Cole Robinson 已提交
6710

6711
    if (!virStoragePoolObjGetConfigFile(obj))
C
Cole Robinson 已提交
6712
        *autostart = 0;
6713
    else
6714
        *autostart = virStoragePoolObjIsAutostart(obj) ? 1 : 0;
C
Cole Robinson 已提交
6715

6716
    virStoragePoolObjEndAPI(&obj);
6717
    return 0;
C
Cole Robinson 已提交
6718 6719
}

6720

C
Cole Robinson 已提交
6721
static int
6722
testStoragePoolSetAutostart(virStoragePoolPtr pool,
6723 6724
                            int autostart)
{
6725
    testDriverPtr privconn = pool->conn->privateData;
6726
    virStoragePoolObjPtr obj;
6727
    bool new_autostart = (autostart != 0);
6728
    int ret = -1;
6729

6730
    if (!(obj = testStoragePoolObjFindByName(privconn, pool->name)))
6731
        return -1;
C
Cole Robinson 已提交
6732

6733
    if (!virStoragePoolObjGetConfigFile(obj)) {
6734 6735
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("pool has no config file"));
6736
        goto cleanup;
C
Cole Robinson 已提交
6737 6738
    }

6739
    virStoragePoolObjSetAutostart(obj, new_autostart);
6740 6741
    ret = 0;

6742
 cleanup:
6743
    virStoragePoolObjEndAPI(&obj);
6744
    return ret;
C
Cole Robinson 已提交
6745 6746 6747 6748
}


static int
6749 6750
testStoragePoolNumOfVolumes(virStoragePoolPtr pool)
{
6751
    testDriverPtr privconn = pool->conn->privateData;
6752
    virStoragePoolObjPtr obj;
6753
    int ret = -1;
6754

6755 6756
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return -1;
C
Cole Robinson 已提交
6757

6758
    ret = virStoragePoolObjNumOfVolumes(obj, pool->conn, NULL);
6759

6760
    virStoragePoolObjEndAPI(&obj);
6761
    return ret;
C
Cole Robinson 已提交
6762 6763
}

6764

C
Cole Robinson 已提交
6765
static int
6766
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
6767
                           char **const names,
6768 6769
                           int maxnames)
{
6770
    testDriverPtr privconn = pool->conn->privateData;
6771
    virStoragePoolObjPtr obj;
6772
    int n = -1;
6773

6774
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
6775
        return -1;
6776

6777
    n = virStoragePoolObjVolumeGetNames(obj, pool->conn, NULL, names, maxnames);
C
Cole Robinson 已提交
6778

6779
    virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
6780 6781 6782
    return n;
}

6783

6784
static int
6785
testStoragePoolListAllVolumes(virStoragePoolPtr pool,
6786
                              virStorageVolPtr **vols,
6787 6788
                              unsigned int flags)
{
6789 6790
    testDriverPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr obj;
6791 6792 6793 6794
    int ret = -1;

    virCheckFlags(0, -1);

6795
    if (!(obj = testStoragePoolObjFindByUUID(privconn, pool->uuid)))
6796
        return -1;
6797

6798
    if (!virStoragePoolObjIsActive(obj)) {
6799 6800 6801 6802 6803
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("storage pool is not active"));
        goto cleanup;
    }

6804
    ret = virStoragePoolObjVolumeListExport(pool->conn, obj, vols, NULL);
6805 6806

 cleanup:
6807
    virStoragePoolObjEndAPI(&obj);
6808 6809 6810

    return ret;
}
C
Cole Robinson 已提交
6811

6812

6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827
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 已提交
6828
static virStorageVolPtr
6829
testStorageVolLookupByName(virStoragePoolPtr pool,
6830
                           const char *name)
6831
{
6832
    testDriverPtr privconn = pool->conn->privateData;
6833
    virStoragePoolObjPtr obj;
6834
    virStoragePoolDefPtr def;
6835
    virStorageVolDefPtr privvol;
6836
    virStorageVolPtr ret = NULL;
6837

6838 6839
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return NULL;
6840
    def = virStoragePoolObjGetDef(obj);
6841

6842
    if (!(privvol = testStorageVolDefFindByName(obj, name)))
6843
        goto cleanup;
C
Cole Robinson 已提交
6844

6845
    ret = virGetStorageVol(pool->conn, def->name,
6846 6847
                           privvol->name, privvol->key,
                           NULL, NULL);
6848

6849
 cleanup:
6850
    virStoragePoolObjEndAPI(&obj);
6851
    return ret;
C
Cole Robinson 已提交
6852 6853 6854
}


6855 6856 6857 6858 6859 6860 6861 6862 6863 6864
struct storageVolLookupData {
    const char *key;
    const char *path;
    virStorageVolDefPtr voldef;
};

static bool
testStorageVolLookupByKeyCallback(virStoragePoolObjPtr obj,
                                  const void *opaque)
{
6865
    struct storageVolLookupData *data = (struct storageVolLookupData *)opaque;
6866 6867 6868 6869 6870 6871 6872 6873

    if (virStoragePoolObjIsActive(obj))
        data->voldef = virStorageVolDefFindByKey(obj, data->key);

    return !!data->voldef;
}


C
Cole Robinson 已提交
6874
static virStorageVolPtr
6875
testStorageVolLookupByKey(virConnectPtr conn,
6876 6877
                          const char *key)
{
6878
    testDriverPtr privconn = conn->privateData;
6879
    virStoragePoolObjPtr obj;
6880
    virStoragePoolDefPtr def;
6881
    struct storageVolLookupData data = {
6882
        .key = key, .voldef = NULL };
6883
    virStorageVolPtr vol = NULL;
C
Cole Robinson 已提交
6884

6885
    virObjectLock(privconn);
6886
    if ((obj = virStoragePoolObjListSearch(privconn->pools,
6887 6888
                                           testStorageVolLookupByKeyCallback,
                                           &data)) && data.voldef) {
6889
        def = virStoragePoolObjGetDef(obj);
6890 6891 6892
        vol = virGetStorageVol(conn, def->name,
                               data.voldef->name, data.voldef->key,
                               NULL, NULL);
6893
        virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
6894
    }
6895
    virObjectUnlock(privconn);
C
Cole Robinson 已提交
6896

6897
    if (!vol)
6898 6899
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching key '%s'"), key);
6900

6901 6902 6903 6904 6905 6906 6907 6908
    return vol;
}


static bool
testStorageVolLookupByPathCallback(virStoragePoolObjPtr obj,
                                   const void *opaque)
{
6909
    struct storageVolLookupData *data = (struct storageVolLookupData *)opaque;
6910 6911 6912 6913 6914

    if (virStoragePoolObjIsActive(obj))
        data->voldef = virStorageVolDefFindByPath(obj, data->path);

    return !!data->voldef;
C
Cole Robinson 已提交
6915 6916
}

6917

C
Cole Robinson 已提交
6918
static virStorageVolPtr
6919
testStorageVolLookupByPath(virConnectPtr conn,
6920 6921
                           const char *path)
{
6922
    testDriverPtr privconn = conn->privateData;
6923
    virStoragePoolObjPtr obj;
6924
    virStoragePoolDefPtr def;
6925
    struct storageVolLookupData data = {
6926
        .path = path, .voldef = NULL };
6927
    virStorageVolPtr vol = NULL;
C
Cole Robinson 已提交
6928

6929
    virObjectLock(privconn);
6930
    if ((obj = virStoragePoolObjListSearch(privconn->pools,
6931 6932
                                           testStorageVolLookupByPathCallback,
                                           &data)) && data.voldef) {
6933
        def = virStoragePoolObjGetDef(obj);
6934 6935 6936
        vol = virGetStorageVol(conn, def->name,
                               data.voldef->name, data.voldef->key,
                               NULL, NULL);
6937
        virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
6938
    }
6939
    virObjectUnlock(privconn);
C
Cole Robinson 已提交
6940

6941
    if (!vol)
6942 6943
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching path '%s'"), path);
6944

6945
    return vol;
C
Cole Robinson 已提交
6946 6947
}

6948

C
Cole Robinson 已提交
6949
static virStorageVolPtr
6950 6951 6952
testStorageVolCreateXML(virStoragePoolPtr pool,
                        const char *xmldesc,
                        unsigned int flags)
E
Eric Blake 已提交
6953
{
6954
    testDriverPtr privconn = pool->conn->privateData;
6955
    virStoragePoolObjPtr obj;
6956
    virStoragePoolDefPtr def;
6957
    virStorageVolPtr ret = NULL;
J
Ján Tomko 已提交
6958
    g_autoptr(virStorageVolDef) privvol = NULL;
6959

E
Eric Blake 已提交
6960 6961
    virCheckFlags(0, NULL);

6962 6963
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return NULL;
6964
    def = virStoragePoolObjGetDef(obj);
C
Cole Robinson 已提交
6965

6966
    privvol = virStorageVolDefParseString(def, xmldesc, 0);
6967
    if (privvol == NULL)
6968
        goto cleanup;
6969

6970
    if (virStorageVolDefFindByName(obj, privvol->name)) {
6971 6972
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
6973
        goto cleanup;
C
Cole Robinson 已提交
6974 6975 6976
    }

    /* Make sure enough space */
6977 6978
    if ((def->allocation + privvol->target.allocation) >
         def->capacity) {
6979 6980 6981
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
6982
        goto cleanup;
C
Cole Robinson 已提交
6983 6984
    }

6985 6986
    privvol->target.path = g_strdup_printf("%s/%s", def->target.path,
                                           privvol->name);
C
Cole Robinson 已提交
6987

6988 6989
    privvol->key = g_strdup(privvol->target.path);
    if (virStoragePoolObjAddVol(obj, privvol) < 0)
6990
        goto cleanup;
C
Cole Robinson 已提交
6991

6992 6993
    def->allocation += privvol->target.allocation;
    def->available = (def->capacity - def->allocation);
C
Cole Robinson 已提交
6994

6995
    ret = virGetStorageVol(pool->conn, def->name,
6996 6997
                           privvol->name, privvol->key,
                           NULL, NULL);
6998
    privvol = NULL;
6999

7000
 cleanup:
7001
    virStoragePoolObjEndAPI(&obj);
7002
    return ret;
C
Cole Robinson 已提交
7003 7004
}

7005

7006
static virStorageVolPtr
7007 7008 7009 7010
testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
                            const char *xmldesc,
                            virStorageVolPtr clonevol,
                            unsigned int flags)
E
Eric Blake 已提交
7011
{
7012
    testDriverPtr privconn = pool->conn->privateData;
7013
    virStoragePoolObjPtr obj;
7014
    virStoragePoolDefPtr def;
7015
    virStorageVolDefPtr origvol = NULL;
7016
    virStorageVolPtr ret = NULL;
J
Ján Tomko 已提交
7017
    g_autoptr(virStorageVolDef) privvol = NULL;
7018

E
Eric Blake 已提交
7019 7020
    virCheckFlags(0, NULL);

7021 7022
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, pool->name)))
        return NULL;
7023
    def = virStoragePoolObjGetDef(obj);
7024

7025
    privvol = virStorageVolDefParseString(def, xmldesc, 0);
7026 7027 7028
    if (privvol == NULL)
        goto cleanup;

7029
    if (virStorageVolDefFindByName(obj, privvol->name)) {
7030 7031
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
7032 7033 7034
        goto cleanup;
    }

7035
    origvol = virStorageVolDefFindByName(obj, clonevol->name);
7036
    if (!origvol) {
7037 7038 7039
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       clonevol->name);
7040 7041 7042 7043
        goto cleanup;
    }

    /* Make sure enough space */
7044
    if ((def->allocation + privvol->target.allocation) > def->capacity) {
7045 7046 7047
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
7048 7049
        goto cleanup;
    }
7050
    def->available = (def->capacity - def->allocation);
7051

7052 7053
    privvol->target.path = g_strdup_printf("%s/%s", def->target.path,
                                           privvol->name);
7054

7055 7056
    privvol->key = g_strdup(privvol->target.path);
    if (virStoragePoolObjAddVol(obj, privvol) < 0)
7057 7058
        goto cleanup;

7059 7060
    def->allocation += privvol->target.allocation;
    def->available = (def->capacity - def->allocation);
7061

7062
    ret = virGetStorageVol(pool->conn, def->name,
7063 7064
                           privvol->name, privvol->key,
                           NULL, NULL);
7065 7066
    privvol = NULL;

7067
 cleanup:
7068
    virStoragePoolObjEndAPI(&obj);
7069 7070 7071
    return ret;
}

7072

C
Cole Robinson 已提交
7073
static int
7074 7075
testStorageVolDelete(virStorageVolPtr vol,
                     unsigned int flags)
E
Eric Blake 已提交
7076
{
7077
    testDriverPtr privconn = vol->conn->privateData;
7078
    virStoragePoolObjPtr obj;
7079
    virStoragePoolDefPtr def;
7080
    virStorageVolDefPtr privvol;
7081
    int ret = -1;
C
Cole Robinson 已提交
7082

E
Eric Blake 已提交
7083 7084
    virCheckFlags(0, -1);

7085 7086
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return -1;
7087
    def = virStoragePoolObjGetDef(obj);
7088

7089
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
7090
        goto cleanup;
7091

7092 7093
    def->allocation -= privvol->target.allocation;
    def->available = (def->capacity - def->allocation);
C
Cole Robinson 已提交
7094

7095
    virStoragePoolObjRemoveVol(obj, privvol);
C
Cole Robinson 已提交
7096

7097
    ret = 0;
C
Cole Robinson 已提交
7098

7099
 cleanup:
7100
    virStoragePoolObjEndAPI(&obj);
7101
    return ret;
C
Cole Robinson 已提交
7102 7103 7104
}


7105 7106
static int
testStorageVolumeTypeForPool(int pooltype)
7107
{
7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129
    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 已提交
7130 7131 7132
    }
}

7133

C
Cole Robinson 已提交
7134
static int
7135
testStorageVolGetInfo(virStorageVolPtr vol,
7136 7137
                      virStorageVolInfoPtr info)
{
7138
    testDriverPtr privconn = vol->conn->privateData;
7139
    virStoragePoolObjPtr obj;
7140
    virStoragePoolDefPtr def;
7141
    virStorageVolDefPtr privvol;
7142
    int ret = -1;
7143

7144 7145
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return -1;
7146
    def = virStoragePoolObjGetDef(obj);
7147

7148
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
7149
        goto cleanup;
7150

C
Cole Robinson 已提交
7151
    memset(info, 0, sizeof(*info));
7152 7153
    if ((info->type = testStorageVolumeTypeForPool(def->type)) < 0)
        goto cleanup;
7154 7155
    info->capacity = privvol->target.capacity;
    info->allocation = privvol->target.allocation;
7156
    ret = 0;
C
Cole Robinson 已提交
7157

7158
 cleanup:
7159
    virStoragePoolObjEndAPI(&obj);
7160
    return ret;
C
Cole Robinson 已提交
7161 7162
}

7163

C
Cole Robinson 已提交
7164
static char *
7165 7166
testStorageVolGetXMLDesc(virStorageVolPtr vol,
                         unsigned int flags)
E
Eric Blake 已提交
7167
{
7168
    testDriverPtr privconn = vol->conn->privateData;
7169
    virStoragePoolObjPtr obj;
7170
    virStorageVolDefPtr privvol;
7171
    char *ret = NULL;
7172

E
Eric Blake 已提交
7173 7174
    virCheckFlags(0, NULL);

7175 7176
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return NULL;
7177

7178
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
7179
        goto cleanup;
C
Cole Robinson 已提交
7180

7181
    ret = virStorageVolDefFormat(virStoragePoolObjGetDef(obj), privvol);
7182

7183
 cleanup:
7184
    virStoragePoolObjEndAPI(&obj);
7185
    return ret;
C
Cole Robinson 已提交
7186 7187
}

7188

C
Cole Robinson 已提交
7189
static char *
7190 7191
testStorageVolGetPath(virStorageVolPtr vol)
{
7192
    testDriverPtr privconn = vol->conn->privateData;
7193
    virStoragePoolObjPtr obj;
7194
    virStorageVolDefPtr privvol;
7195
    char *ret = NULL;
7196

7197 7198
    if (!(obj = testStoragePoolObjFindActiveByName(privconn, vol->pool)))
        return NULL;
7199

7200
    if (!(privvol = testStorageVolDefFindByName(obj, vol->name)))
7201
        goto cleanup;
7202

7203
    ret = g_strdup(privvol->target.path);
7204

7205
 cleanup:
7206
    virStoragePoolObjEndAPI(&obj);
C
Cole Robinson 已提交
7207 7208 7209
    return ret;
}

7210

7211
/* Node device implementations */
7212

7213 7214 7215 7216 7217 7218
static virNodeDeviceObjPtr
testNodeDeviceObjFindByName(testDriverPtr driver,
                            const char *name)
{
    virNodeDeviceObjPtr obj;

7219
    if (!(obj = virNodeDeviceObjListFindByName(driver->devs, name)))
7220 7221 7222 7223 7224 7225 7226 7227
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       name);

    return obj;
}


7228 7229 7230
static int
testNodeNumOfDevices(virConnectPtr conn,
                     const char *cap,
E
Eric Blake 已提交
7231
                     unsigned int flags)
7232
{
7233
    testDriverPtr driver = conn->privateData;
7234

E
Eric Blake 已提交
7235 7236
    virCheckFlags(0, -1);

7237
    return virNodeDeviceObjListNumOfDevices(driver->devs, conn, cap, NULL);
7238 7239
}

7240

7241 7242 7243 7244 7245
static int
testNodeListDevices(virConnectPtr conn,
                    const char *cap,
                    char **const names,
                    int maxnames,
E
Eric Blake 已提交
7246
                    unsigned int flags)
7247
{
7248
    testDriverPtr driver = conn->privateData;
7249

E
Eric Blake 已提交
7250 7251
    virCheckFlags(0, -1);

7252 7253
    return virNodeDeviceObjListGetNames(driver->devs, conn, NULL,
                                        cap, names, maxnames);
7254 7255
}

7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267
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);
}
7268

7269 7270 7271
static virNodeDevicePtr
testNodeDeviceLookupByName(virConnectPtr conn, const char *name)
{
7272
    testDriverPtr driver = conn->privateData;
7273
    virNodeDeviceObjPtr obj;
7274
    virNodeDeviceDefPtr def;
7275 7276
    virNodeDevicePtr ret = NULL;

7277
    if (!(obj = testNodeDeviceObjFindByName(driver, name)))
7278
        return NULL;
7279
    def = virNodeDeviceObjGetDef(obj);
7280

7281 7282
    if ((ret = virGetNodeDevice(conn, name)))
        ret->parentName = g_strdup(def->parent);
7283

7284
    virNodeDeviceObjEndAPI(&obj);
7285 7286 7287 7288
    return ret;
}

static char *
7289
testNodeDeviceGetXMLDesc(virNodeDevicePtr dev,
E
Eric Blake 已提交
7290
                         unsigned int flags)
7291
{
7292
    testDriverPtr driver = dev->conn->privateData;
7293 7294 7295
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

E
Eric Blake 已提交
7296 7297
    virCheckFlags(0, NULL);

7298
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
7299
        return NULL;
7300

7301
    ret = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(obj));
7302

7303
    virNodeDeviceObjEndAPI(&obj);
7304 7305 7306 7307 7308 7309
    return ret;
}

static char *
testNodeDeviceGetParent(virNodeDevicePtr dev)
{
7310
    testDriverPtr driver = dev->conn->privateData;
7311
    virNodeDeviceObjPtr obj;
7312
    virNodeDeviceDefPtr def;
7313 7314
    char *ret = NULL;

7315
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
7316
        return NULL;
7317
    def = virNodeDeviceObjGetDef(obj);
7318

7319
    if (def->parent) {
7320
        ret = g_strdup(def->parent);
7321
    } else {
7322 7323
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no parent for this device"));
7324 7325
    }

7326
    virNodeDeviceObjEndAPI(&obj);
7327 7328 7329
    return ret;
}

7330

7331 7332 7333
static int
testNodeDeviceNumOfCaps(virNodeDevicePtr dev)
{
7334
    testDriverPtr driver = dev->conn->privateData;
7335
    virNodeDeviceObjPtr obj;
7336
    virNodeDeviceDefPtr def;
7337 7338 7339
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;

7340
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
7341
        return -1;
7342
    def = virNodeDeviceObjGetDef(obj);
7343

7344
    for (caps = def->caps; caps; caps = caps->next)
7345 7346
        ++ncaps;

7347
    virNodeDeviceObjEndAPI(&obj);
7348
    return ncaps;
7349 7350 7351 7352 7353 7354
}


static int
testNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
7355
    testDriverPtr driver = dev->conn->privateData;
7356
    virNodeDeviceObjPtr obj;
7357
    virNodeDeviceDefPtr def;
7358 7359 7360
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;

7361
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
7362
        return -1;
7363
    def = virNodeDeviceObjGetDef(obj);
7364

7365
    for (caps = def->caps; caps && ncaps < maxnames; caps = caps->next) {
7366
        names[ncaps] = g_strdup(virNodeDevCapTypeToString(caps->data.type));
7367
        ncaps++;
7368 7369
    }

7370
    virNodeDeviceObjEndAPI(&obj);
7371
    return ncaps;
7372 7373
}

7374

7375 7376
static virNodeDeviceObjPtr
testNodeDeviceMockCreateVport(testDriverPtr driver,
7377
                              const char *wwnn,
7378
                              const char *wwpn)
7379
{
7380
    virNodeDeviceDefPtr def = NULL;
7381
    virNodeDevCapsDefPtr caps;
7382
    virNodeDeviceObjPtr obj = NULL, objcopy = NULL;
7383
    virNodeDeviceDefPtr objdef;
7384
    virObjectEventPtr event = NULL;
7385
    g_autofree char *xml = NULL;
7386

7387 7388 7389 7390 7391 7392 7393 7394 7395
    /* 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. */
7396 7397
    if (!(objcopy = virNodeDeviceObjListFindByName(driver->devs,
                                                   "scsi_host11")))
7398 7399
        goto cleanup;

7400
    xml = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(objcopy));
7401
    virNodeDeviceObjEndAPI(&objcopy);
7402 7403 7404 7405
    if (!xml)
        goto cleanup;

    if (!(def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL)))
7406 7407
        goto cleanup;

7408
    VIR_FREE(def->name);
7409
    def->name = g_strdup("scsi_host12");
7410

7411 7412 7413
    /* 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. */
7414 7415
    caps = def->caps;
    while (caps) {
7416
        if (caps->data.type != VIR_NODE_DEV_CAP_SCSI_HOST)
7417 7418
            continue;

7419 7420 7421 7422
        /* 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);
7423 7424
            caps->data.scsi_host.wwnn = g_strdup(wwnn);
            caps->data.scsi_host.wwpn = g_strdup(wwpn);
7425 7426 7427 7428 7429 7430 7431
        } 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++;
        }
7432 7433 7434
        caps = caps->next;
    }

7435
    if (!(obj = virNodeDeviceObjListAssignDef(driver->devs, def)))
7436
        goto cleanup;
7437
    virNodeDeviceObjSetSkipUpdateCaps(obj, true);
7438
    def = NULL;
7439
    objdef = virNodeDeviceObjGetDef(obj);
7440

7441
    event = virNodeDeviceEventLifecycleNew(objdef->name,
7442 7443
                                           VIR_NODE_DEVICE_EVENT_CREATED,
                                           0);
7444
    virObjectEventStateQueue(driver->eventState, event);
7445 7446

 cleanup:
7447 7448
    virNodeDeviceDefFree(def);
    return obj;
7449 7450 7451 7452 7453 7454 7455 7456 7457 7458
}


static virNodeDevicePtr
testNodeDeviceCreateXML(virConnectPtr conn,
                        const char *xmlDesc,
                        unsigned int flags)
{
    testDriverPtr driver = conn->privateData;
    virNodeDeviceDefPtr def = NULL;
7459 7460
    virNodeDevicePtr dev = NULL, ret = NULL;
    virNodeDeviceObjPtr obj = NULL;
7461
    virNodeDeviceDefPtr objdef;
7462 7463
    g_autofree char *wwnn = NULL;
    g_autofree char *wwpn = NULL;
7464 7465 7466 7467 7468 7469

    virCheckFlags(0, NULL);

    if (!(def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, NULL)))
        goto cleanup;

7470 7471 7472
    /* We run this simply for validation - it essentially validates that
     * the input XML either has a wwnn/wwpn or virNodeDevCapSCSIHostParseXML
     * generated a wwnn/wwpn */
7473 7474 7475
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) < 0)
        goto cleanup;

7476 7477 7478
    /* 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. */
7479
    if (virNodeDeviceObjListGetParentHost(driver->devs, def) < 0)
7480 7481 7482 7483
        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
7484 7485 7486
     * 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 */
7487 7488
    if (!(obj = testNodeDeviceMockCreateVport(driver, wwnn, wwpn)))
        goto cleanup;
7489
    objdef = virNodeDeviceObjGetDef(obj);
7490

7491
    if (!(dev = virGetNodeDevice(conn, objdef->name)))
7492 7493
        goto cleanup;

7494
    VIR_FREE(dev->parentName);
7495
    dev->parentName = g_strdup(def->parent);
7496

7497
    ret = g_steal_pointer(&dev);
7498

7499
 cleanup:
7500
    virNodeDeviceObjEndAPI(&obj);
7501
    virNodeDeviceDefFree(def);
7502 7503
    virObjectUnref(dev);
    return ret;
7504 7505 7506 7507 7508 7509
}

static int
testNodeDeviceDestroy(virNodeDevicePtr dev)
{
    int ret = 0;
7510
    testDriverPtr driver = dev->conn->privateData;
7511
    virNodeDeviceObjPtr obj = NULL;
7512
    virNodeDeviceObjPtr parentobj = NULL;
7513
    virNodeDeviceDefPtr def;
7514
    virObjectEventPtr event = NULL;
7515 7516
    g_autofree char *wwnn = NULL;
    g_autofree char *wwpn = NULL;
7517

7518
    if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
7519
        return -1;
7520
    def = virNodeDeviceObjGetDef(obj);
7521

7522
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) == -1)
7523
        goto cleanup;
7524

7525 7526 7527 7528
    /* 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 */
7529
    virObjectUnlock(obj);
7530

7531 7532 7533 7534 7535 7536
    /* 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);
7537
        virObjectLock(obj);
7538
        goto cleanup;
7539
    }
7540
    virNodeDeviceObjEndAPI(&parentobj);
7541

7542 7543 7544 7545
    event = virNodeDeviceEventLifecycleNew(dev->name,
                                           VIR_NODE_DEVICE_EVENT_DELETED,
                                           0);

7546
    virObjectLock(obj);
7547
    virNodeDeviceObjListRemove(driver->devs, obj);
7548
    virObjectUnref(obj);
7549
    obj = NULL;
7550

7551
 cleanup:
7552
    virNodeDeviceObjEndAPI(&obj);
7553
    virObjectEventStateQueue(driver->eventState, event);
7554 7555 7556
    return ret;
}

7557 7558

/* Domain event implementations */
7559
static int
7560 7561 7562 7563
testConnectDomainEventRegister(virConnectPtr conn,
                               virConnectDomainEventCallback callback,
                               void *opaque,
                               virFreeCallback freecb)
7564
{
7565
    testDriverPtr driver = conn->privateData;
7566
    int ret = 0;
7567

7568
    if (virDomainEventStateRegister(conn, driver->eventState,
7569 7570
                                    callback, opaque, freecb) < 0)
        ret = -1;
7571 7572 7573 7574

    return ret;
}

7575

7576
static int
7577 7578
testConnectDomainEventDeregister(virConnectPtr conn,
                                 virConnectDomainEventCallback callback)
7579
{
7580
    testDriverPtr driver = conn->privateData;
7581
    int ret = 0;
7582

7583
    if (virDomainEventStateDeregister(conn, driver->eventState,
7584 7585
                                      callback) < 0)
        ret = -1;
7586 7587 7588 7589

    return ret;
}

7590 7591

static int
7592 7593 7594 7595 7596 7597
testConnectDomainEventRegisterAny(virConnectPtr conn,
                                  virDomainPtr dom,
                                  int eventID,
                                  virConnectDomainEventGenericCallback callback,
                                  void *opaque,
                                  virFreeCallback freecb)
7598
{
7599
    testDriverPtr driver = conn->privateData;
7600 7601
    int ret;

7602
    if (virDomainEventStateRegisterID(conn, driver->eventState,
7603 7604
                                      dom, eventID,
                                      callback, opaque, freecb, &ret) < 0)
7605
        ret = -1;
7606 7607 7608 7609 7610

    return ret;
}

static int
7611 7612
testConnectDomainEventDeregisterAny(virConnectPtr conn,
                                    int callbackID)
7613
{
7614
    testDriverPtr driver = conn->privateData;
7615
    int ret = 0;
7616

7617
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
7618
                                        callbackID, true) < 0)
7619
        ret = -1;
7620 7621 7622 7623 7624

    return ret;
}


7625 7626 7627 7628 7629 7630 7631 7632
static int
testConnectNetworkEventRegisterAny(virConnectPtr conn,
                                   virNetworkPtr net,
                                   int eventID,
                                   virConnectNetworkEventGenericCallback callback,
                                   void *opaque,
                                   virFreeCallback freecb)
{
7633
    testDriverPtr driver = conn->privateData;
7634 7635
    int ret;

7636
    if (virNetworkEventStateRegisterID(conn, driver->eventState,
7637
                                       net, eventID, callback,
7638 7639 7640 7641 7642 7643 7644 7645 7646 7647
                                       opaque, freecb, &ret) < 0)
        ret = -1;

    return ret;
}

static int
testConnectNetworkEventDeregisterAny(virConnectPtr conn,
                                     int callbackID)
{
7648
    testDriverPtr driver = conn->privateData;
7649
    int ret = 0;
7650

7651
    if (virObjectEventStateDeregisterID(conn, driver->eventState,
7652
                                        callbackID, true) < 0)
7653
        ret = -1;
7654 7655 7656 7657

    return ret;
}

7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 7671 7672 7673 7674 7675 7676 7677 7678 7679 7680 7681 7682 7683 7684
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,
7685
                                        callbackID, true) < 0)
7686 7687 7688 7689 7690
        ret = -1;

    return ret;
}

7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717
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,
7718
                                        callbackID, true) < 0)
7719 7720 7721 7722 7723
        ret = -1;

    return ret;
}

7724 7725 7726
static int testConnectListAllDomains(virConnectPtr conn,
                                     virDomainPtr **domains,
                                     unsigned int flags)
7727
{
7728
    testDriverPtr privconn = conn->privateData;
7729

O
Osier Yang 已提交
7730
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
7731

7732 7733
    return virDomainObjListExport(privconn->domains, conn, domains,
                                  NULL, flags);
7734 7735
}

7736
static int
J
Ján Tomko 已提交
7737
testNodeGetCPUMap(virConnectPtr conn G_GNUC_UNUSED,
7738 7739 7740 7741 7742 7743 7744
                  unsigned char **cpumap,
                  unsigned int *online,
                  unsigned int flags)
{
    virCheckFlags(0, -1);

    if (cpumap) {
7745
        if (VIR_ALLOC_N(*cpumap, 1) < 0)
P
Peter Krempa 已提交
7746
            return -1;
7747 7748 7749 7750 7751 7752
        *cpumap[0] = 0x15;
    }

    if (online)
        *online = 3;

P
Peter Krempa 已提交
7753
    return  8;
7754 7755
}

7756
static char *
J
Ján Tomko 已提交
7757
testDomainScreenshot(virDomainPtr dom G_GNUC_UNUSED,
7758
                     virStreamPtr st,
J
Ján Tomko 已提交
7759
                     unsigned int screen G_GNUC_UNUSED,
7760 7761 7762 7763 7764 7765
                     unsigned int flags)
{
    char *ret = NULL;

    virCheckFlags(0, NULL);

7766
    ret = g_strdup("image/png");
7767

D
Daniel P. Berrange 已提交
7768
    if (virFDStreamOpenFile(st, PKGDATADIR "/test-screenshot.png", 0, 0, O_RDONLY) < 0)
7769 7770 7771 7772 7773
        VIR_FREE(ret);

    return ret;
}

7774

7775 7776 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797
static int
testDomainInjectNMI(virDomainPtr domain,
                    unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

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

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

    /* do nothing */
    ret = 0;
 cleanup:
    virDomainObjEndAPI(&vm);
    return ret;
}


7798 7799 7800
static int
testDomainSendKey(virDomainPtr domain,
                  unsigned int codeset,
J
Ján Tomko 已提交
7801
                  unsigned int holdtime G_GNUC_UNUSED,
7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835
                  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;
}


7836
static int
J
Ján Tomko 已提交
7837
testConnectGetCPUModelNames(virConnectPtr conn G_GNUC_UNUSED,
J
Jiri Denemark 已提交
7838
                            const char *archName,
7839 7840 7841
                            char ***models,
                            unsigned int flags)
{
J
Jiri Denemark 已提交
7842 7843
    virArch arch;

7844
    virCheckFlags(0, -1);
J
Jiri Denemark 已提交
7845 7846 7847 7848 7849 7850 7851 7852

    if (!(arch = virArchFromString(archName))) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("cannot find architecture %s"),
                       archName);
        return -1;
    }

J
Jiri Denemark 已提交
7853
    return virCPUGetModels(arch, models);
7854
}
7855

C
Cole Robinson 已提交
7856 7857 7858
static int
testDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
7859
    testDriverPtr privconn = dom->conn->privateData;
C
Cole Robinson 已提交
7860
    virDomainObjPtr vm = NULL;
7861
    virObjectEventPtr event = NULL;
C
Cole Robinson 已提交
7862 7863 7864 7865 7866 7867
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
                  VIR_DOMAIN_SAVE_RUNNING |
                  VIR_DOMAIN_SAVE_PAUSED, -1);

7868 7869
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
7870

7871
    if (virDomainObjCheckActive(vm) < 0)
C
Cole Robinson 已提交
7872 7873 7874 7875 7876 7877 7878 7879 7880
        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);
7881
    event = virDomainEventLifecycleNewFromObj(vm,
C
Cole Robinson 已提交
7882 7883 7884 7885 7886
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
    vm->hasManagedSave = true;

    ret = 0;
7887
 cleanup:
7888
    virDomainObjEndAPI(&vm);
7889
    virObjectEventStateQueue(privconn->eventState, event);
C
Cole Robinson 已提交
7890 7891 7892 7893 7894 7895 7896 7897 7898

    return ret;
}


static int
testDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm;
7899
    int ret;
C
Cole Robinson 已提交
7900 7901 7902

    virCheckFlags(0, -1);

7903 7904
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
7905 7906

    ret = vm->hasManagedSave;
7907

7908
    virDomainObjEndAPI(&vm);
C
Cole Robinson 已提交
7909 7910 7911 7912 7913 7914 7915 7916 7917 7918
    return ret;
}

static int
testDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm;

    virCheckFlags(0, -1);

7919 7920
    if (!(vm = testDomObjFromDomain(dom)))
        return -1;
C
Cole Robinson 已提交
7921 7922

    vm->hasManagedSave = false;
7923

7924
    virDomainObjEndAPI(&vm);
7925
    return 0;
C
Cole Robinson 已提交
7926 7927
}

7928 7929 7930 7931 7932 7933 7934 7935 7936 7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 7963 7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 7974 7975 7976 7977 7978 7979 7980

static int
testDomainMemoryStats(virDomainPtr dom,
                      virDomainMemoryStatPtr stats,
                      unsigned int nr_stats,
                      unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int cur_memory;
    int ret = -1;

    virCheckFlags(0, -1);

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

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

    cur_memory = vm->def->mem.cur_balloon;
    ret = 0;

#define STATS_SET_PARAM(name, value) \
    if (ret < nr_stats) { \
        stats[ret].tag = name; \
        stats[ret].val = value; \
        ret++; \
    }

    if (virDomainDefHasMemballoon(vm->def)) {
        STATS_SET_PARAM(VIR_DOMAIN_MEMORY_STAT_ACTUAL_BALLOON, cur_memory);
        STATS_SET_PARAM(VIR_DOMAIN_MEMORY_STAT_SWAP_IN, 0);
        STATS_SET_PARAM(VIR_DOMAIN_MEMORY_STAT_SWAP_OUT, 0);
        STATS_SET_PARAM(VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT, 0);
        STATS_SET_PARAM(VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT, 0);
        STATS_SET_PARAM(VIR_DOMAIN_MEMORY_STAT_UNUSED, cur_memory / 2);
        STATS_SET_PARAM(VIR_DOMAIN_MEMORY_STAT_AVAILABLE, cur_memory);
        STATS_SET_PARAM(VIR_DOMAIN_MEMORY_STAT_USABLE, cur_memory / 2);
        STATS_SET_PARAM(VIR_DOMAIN_MEMORY_STAT_LAST_UPDATE, 627319920);
        STATS_SET_PARAM(VIR_DOMAIN_MEMORY_STAT_DISK_CACHES, cur_memory / 8);
        STATS_SET_PARAM(VIR_DOMAIN_MEMORY_STAT_HUGETLB_PGALLOC, 0);
        STATS_SET_PARAM(VIR_DOMAIN_MEMORY_STAT_HUGETLB_PGFAIL, 0);
        STATS_SET_PARAM(VIR_DOMAIN_MEMORY_STAT_RSS, cur_memory / 2);
    }

#undef STATS_SET_PARAM

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


7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016
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 已提交
8017

8018 8019 8020 8021 8022 8023 8024 8025 8026 8027 8028 8029 8030 8031 8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056
static int
testDomainGetBlockInfo(virDomainPtr dom,
                       const char *path,
                       virDomainBlockInfoPtr info,
                       unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainDiskDefPtr disk;
    int ret = -1;

    virCheckFlags(0, -1);

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

    if (!(disk = virDomainDiskByName(vm->def, path, false))) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path %s not assigned to domain"), path);
        goto cleanup;
    }

    if (virStorageSourceIsEmpty(disk->src)) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("disk '%s' does not currently have a source assigned"),
                       path);
        goto cleanup;
    }

    info->capacity = 1099506450432;
    info->allocation = 1099511627776;
    info->physical = 1099511627776;

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


8057 8058 8059 8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095 8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113
static void
testDomainModifyLifecycleAction(virDomainDefPtr def,
                                virDomainLifecycle type,
                                virDomainLifecycleAction action)
{
    switch (type) {
    case VIR_DOMAIN_LIFECYCLE_POWEROFF:
        def->onPoweroff = action;
        break;
    case VIR_DOMAIN_LIFECYCLE_REBOOT:
        def->onReboot = action;
        break;
    case VIR_DOMAIN_LIFECYCLE_CRASH:
        def->onCrash = action;
        break;
    case VIR_DOMAIN_LIFECYCLE_LAST:
        break;
    }
}


static int
testDomainSetLifecycleAction(virDomainPtr dom,
                             unsigned int type,
                             unsigned int action,
                             unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    virDomainDefPtr persistentDef = NULL;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

    if (!virDomainDefLifecycleActionAllowed(type, action))
        return -1;

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

    if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
        goto cleanup;

    if (def)
        testDomainModifyLifecycleAction(def, type, action);

    if (persistentDef)
        testDomainModifyLifecycleAction(persistentDef, type, action);

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


8114 8115 8116 8117
/*
 * Snapshot APIs
 */

8118
static virDomainMomentObjPtr
8119 8120 8121
testSnapObjFromName(virDomainObjPtr vm,
                    const char *name)
{
8122
    virDomainMomentObjPtr snap = NULL;
8123 8124 8125 8126 8127 8128 8129 8130
    snap = virDomainSnapshotFindByName(vm->snapshots, name);
    if (!snap)
        virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
                       _("no domain snapshot with matching name '%s'"),
                       name);
    return snap;
}

8131
static virDomainMomentObjPtr
8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 8145 8146 8147
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;
8148
    int n;
8149 8150

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
E
Eric Blake 已提交
8151
                  VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
8152 8153 8154
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
8155
        return -1;
8156 8157 8158

    n = virDomainSnapshotObjListNum(vm->snapshots, NULL, flags);

8159
    virDomainObjEndAPI(&vm);
8160 8161 8162 8163 8164 8165 8166 8167 8168 8169
    return n;
}

static int
testDomainSnapshotListNames(virDomainPtr domain,
                            char **names,
                            int nameslen,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
8170
    int n;
8171 8172

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
E
Eric Blake 已提交
8173
                  VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
8174 8175 8176
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
8177
        return -1;
8178 8179 8180 8181

    n = virDomainSnapshotObjListGetNames(vm->snapshots, NULL, names, nameslen,
                                         flags);

8182
    virDomainObjEndAPI(&vm);
8183 8184 8185 8186 8187 8188 8189 8190 8191
    return n;
}

static int
testDomainListAllSnapshots(virDomainPtr domain,
                           virDomainSnapshotPtr **snaps,
                           unsigned int flags)
{
    virDomainObjPtr vm = NULL;
8192
    int n;
8193 8194

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
E
Eric Blake 已提交
8195
                  VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
8196 8197 8198
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromDomain(domain)))
8199
        return -1;
8200 8201 8202

    n = virDomainListSnapshots(vm->snapshots, NULL, domain, snaps, flags);

8203
    virDomainObjEndAPI(&vm);
8204 8205 8206 8207 8208 8209 8210 8211 8212 8213
    return n;
}

static int
testDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
                                    char **names,
                                    int nameslen,
                                    unsigned int flags)
{
    virDomainObjPtr vm = NULL;
8214
    virDomainMomentObjPtr snap = NULL;
8215 8216 8217
    int n = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
E
Eric Blake 已提交
8218
                  VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
8219 8220 8221
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
8222
        return -1;
8223 8224 8225 8226 8227 8228 8229

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    n = virDomainSnapshotObjListGetNames(vm->snapshots, snap, names, nameslen,
                                         flags);

8230
 cleanup:
8231
    virDomainObjEndAPI(&vm);
8232 8233 8234 8235 8236 8237 8238 8239
    return n;
}

static int
testDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot,
                              unsigned int flags)
{
    virDomainObjPtr vm = NULL;
8240
    virDomainMomentObjPtr snap = NULL;
8241 8242 8243
    int n = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
E
Eric Blake 已提交
8244
                  VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
8245 8246 8247
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
8248
        return -1;
8249 8250 8251 8252 8253 8254

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    n = virDomainSnapshotObjListNum(vm->snapshots, snap, flags);

8255
 cleanup:
8256
    virDomainObjEndAPI(&vm);
8257 8258 8259 8260 8261 8262 8263 8264 8265
    return n;
}

static int
testDomainSnapshotListAllChildren(virDomainSnapshotPtr snapshot,
                                  virDomainSnapshotPtr **snaps,
                                  unsigned int flags)
{
    virDomainObjPtr vm = NULL;
8266
    virDomainMomentObjPtr snap = NULL;
8267 8268 8269
    int n = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
E
Eric Blake 已提交
8270
                  VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
8271 8272 8273
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
8274
        return -1;
8275 8276 8277 8278 8279 8280 8281

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    n = virDomainListSnapshots(vm->snapshots, snap, snapshot->domain, snaps,
                               flags);

8282
 cleanup:
8283
    virDomainObjEndAPI(&vm);
8284 8285 8286 8287 8288 8289 8290 8291 8292
    return n;
}

static virDomainSnapshotPtr
testDomainSnapshotLookupByName(virDomainPtr domain,
                               const char *name,
                               unsigned int flags)
{
    virDomainObjPtr vm;
8293
    virDomainMomentObjPtr snap = NULL;
8294 8295 8296 8297 8298
    virDomainSnapshotPtr snapshot = NULL;

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
8299
        return NULL;
8300 8301 8302 8303

    if (!(snap = testSnapObjFromName(vm, name)))
        goto cleanup;

8304
    snapshot = virGetDomainSnapshot(domain, snap->def->name);
8305

8306
 cleanup:
8307
    virDomainObjEndAPI(&vm);
8308 8309 8310 8311 8312 8313 8314 8315
    return snapshot;
}

static int
testDomainHasCurrentSnapshot(virDomainPtr domain,
                             unsigned int flags)
{
    virDomainObjPtr vm;
8316
    int ret;
8317 8318 8319 8320

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromDomain(domain)))
8321
        return -1;
8322

8323
    ret = (virDomainSnapshotGetCurrent(vm->snapshots) != NULL);
8324

8325
    virDomainObjEndAPI(&vm);
8326 8327 8328 8329 8330 8331 8332 8333
    return ret;
}

static virDomainSnapshotPtr
testDomainSnapshotGetParent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm;
8334
    virDomainMomentObjPtr snap = NULL;
8335 8336 8337 8338 8339
    virDomainSnapshotPtr parent = NULL;

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
8340
        return NULL;
8341 8342 8343 8344

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

8345
    if (!snap->def->parent_name) {
8346 8347
        virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
                       _("snapshot '%s' does not have a parent"),
8348
                       snap->def->name);
8349 8350 8351
        goto cleanup;
    }

8352
    parent = virGetDomainSnapshot(snapshot->domain, snap->def->parent_name);
8353

8354
 cleanup:
8355
    virDomainObjEndAPI(&vm);
8356 8357 8358 8359 8360 8361 8362 8363 8364
    return parent;
}

static virDomainSnapshotPtr
testDomainSnapshotCurrent(virDomainPtr domain,
                          unsigned int flags)
{
    virDomainObjPtr vm;
    virDomainSnapshotPtr snapshot = NULL;
8365
    virDomainMomentObjPtr current;
8366 8367 8368 8369

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
8370
        return NULL;
8371

8372 8373
    current = virDomainSnapshotGetCurrent(vm->snapshots);
    if (!current) {
8374 8375 8376 8377 8378
        virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT, "%s",
                       _("the domain does not have a current snapshot"));
        goto cleanup;
    }

8379
    snapshot = virGetDomainSnapshot(domain, current->def->name);
8380

8381
 cleanup:
8382
    virDomainObjEndAPI(&vm);
8383 8384 8385 8386 8387 8388 8389 8390 8391
    return snapshot;
}

static char *
testDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
                             unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    char *xml = NULL;
8392
    virDomainMomentObjPtr snap = NULL;
8393
    char uuidstr[VIR_UUID_STRING_BUFLEN];
8394
    testDriverPtr privconn = snapshot->domain->conn->privateData;
8395

8396
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_XML_SECURE, NULL);
8397 8398

    if (!(vm = testDomObjFromSnapshot(snapshot)))
8399
        return NULL;
8400 8401 8402 8403 8404 8405

    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    virUUIDFormat(snapshot->domain->uuid, uuidstr);

8406
    xml = virDomainSnapshotDefFormat(uuidstr, virDomainSnapshotObjGetDef(snap),
8407
                                     privconn->xmlopt,
8408
                                     virDomainSnapshotFormatConvertXMLFlags(flags));
8409

8410
 cleanup:
8411
    virDomainObjEndAPI(&vm);
8412 8413 8414 8415 8416 8417 8418 8419
    return xml;
}

static int
testDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
8420 8421
    int ret = -1;
    virDomainMomentObjPtr snap = NULL;
8422 8423 8424 8425

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
8426
        return -1;
8427

8428 8429 8430 8431
    if (!(snap = testSnapObjFromSnapshot(vm, snapshot)))
        goto cleanup;

    ret = snap == virDomainSnapshotGetCurrent(vm->snapshots);
8432

8433
 cleanup:
8434
    virDomainObjEndAPI(&vm);
8435 8436 8437 8438 8439 8440 8441 8442 8443 8444 8445 8446 8447 8448
    return ret;
}


static int
testDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot,
                              unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

    if (!(vm = testDomObjFromSnapshot(snapshot)))
8449
        return -1;
8450

C
Cole Robinson 已提交
8451
    if (!testSnapObjFromSnapshot(vm, snapshot))
8452 8453 8454 8455
        goto cleanup;

    ret = 1;

8456
 cleanup:
8457
    virDomainObjEndAPI(&vm);
8458 8459 8460
    return ret;
}

8461 8462 8463 8464 8465 8466
static int
testDomainSnapshotAlignDisks(virDomainObjPtr vm,
                             virDomainSnapshotDefPtr def,
                             unsigned int flags)
{
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
E
Eric Blake 已提交
8467
    bool align_match = true;
8468 8469 8470 8471 8472

    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) {
        align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
        align_match = false;
        if (virDomainObjIsActive(vm))
8473
            def->state = VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT;
8474
        else
8475
            def->state = VIR_DOMAIN_SNAPSHOT_SHUTOFF;
8476 8477 8478 8479 8480 8481 8482
        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);
8483
        def->memory = def->state == VIR_DOMAIN_SNAPSHOT_SHUTOFF ?
8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495
                      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)
{
8496
    testDriverPtr privconn = domain->conn->privateData;
8497
    virDomainObjPtr vm = NULL;
8498
    virDomainMomentObjPtr snap = NULL;
8499
    virDomainSnapshotPtr snapshot = NULL;
8500
    virObjectEventPtr event = NULL;
8501 8502
    bool update_current = true;
    bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
8503
    unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;
8504
    g_autoptr(virDomainSnapshotDef) def = NULL;
8505 8506 8507 8508 8509 8510 8511

    /*
     * DISK_ONLY: Not implemented yet
     * REUSE_EXT: Not implemented yet
     *
     * NO_METADATA: Explicitly not implemented
     *
8512
     * REDEFINE + CURRENT: Implemented
8513 8514 8515 8516 8517 8518
     * HALT: Implemented
     * QUIESCE: Nothing to do
     * ATOMIC: Nothing to do
     * LIVE: Nothing to do
     */
    virCheckFlags(
8519 8520
        VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
        VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
8521 8522 8523
        VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
        VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
        VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
8524 8525
        VIR_DOMAIN_SNAPSHOT_CREATE_LIVE |
        VIR_DOMAIN_SNAPSHOT_CREATE_VALIDATE, NULL);
8526

8527 8528 8529 8530 8531
    if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)))
        update_current = false;
    if (redefine)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;

8532 8533 8534
    if (!(vm = testDomObjFromDomain(domain)))
        goto cleanup;

8535 8536 8537 8538 8539 8540
    if (virDomainListCheckpoints(vm->checkpoints, NULL, domain, NULL, 0) > 0) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("cannot create snapshot while checkpoint exists"));
        goto cleanup;
    }

8541 8542 8543 8544 8545 8546
    if (!vm->persistent && (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT)) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot halt after transient domain snapshot"));
        goto cleanup;
    }

8547 8548 8549
    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_VALIDATE)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_VALIDATE;

8550 8551
    if (!(def = virDomainSnapshotDefParseString(xmlDesc,
                                                privconn->xmlopt,
8552
                                                NULL, NULL,
8553 8554 8555
                                                parse_flags)))
        goto cleanup;

8556
    if (redefine) {
8557
        if (virDomainSnapshotRedefinePrep(vm, &def, &snap,
8558
                                          privconn->xmlopt,
8559
                                          flags) < 0)
8560 8561
            goto cleanup;
    } else {
8562
        if (!(def->parent.dom = virDomainDefCopy(vm->def,
8563 8564 8565
                                                 privconn->xmlopt,
                                                 NULL,
                                                 true)))
8566
            goto cleanup;
8567

8568
        if (testDomainSnapshotAlignDisks(vm, def, flags) < 0)
8569 8570 8571
            goto cleanup;
    }

8572 8573 8574 8575
    if (!snap) {
        if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
            goto cleanup;
        def = NULL;
8576 8577
    }

8578
    if (!redefine) {
8579
        snap->def->parent_name = g_strdup(virDomainSnapshotGetCurrentName(vm->snapshots));
8580 8581 8582 8583 8584

        if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT) &&
            virDomainObjIsActive(vm)) {
            testDomainShutdownState(domain, vm,
                                    VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT);
8585
            event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
8586 8587 8588
                                    VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
        }
    }
8589

8590
    snapshot = virGetDomainSnapshot(domain, snap->def->name);
8591
 cleanup:
8592 8593
    if (vm) {
        if (snapshot) {
8594
            if (update_current)
8595
                virDomainSnapshotSetCurrent(vm->snapshots, snap);
8596
            virDomainSnapshotLinkParent(vm->snapshots, snap);
8597
        }
8598
        virDomainObjEndAPI(&vm);
8599
    }
8600
    virObjectEventStateQueue(privconn->eventState, event);
8601 8602 8603 8604
    return snapshot;
}


8605 8606 8607
typedef struct _testMomentRemoveData testMomentRemoveData;
typedef testMomentRemoveData *testMomentRemoveDataPtr;
struct _testMomentRemoveData {
8608 8609 8610 8611
    virDomainObjPtr vm;
    bool current;
};

8612
static int
8613
testDomainSnapshotDiscardAll(void *payload,
J
Ján Tomko 已提交
8614
                             const void *name G_GNUC_UNUSED,
8615
                             void *data)
8616
{
8617
    virDomainMomentObjPtr snap = payload;
8618
    testMomentRemoveDataPtr curr = data;
8619

8620
    curr->current |= virDomainSnapshotObjListRemove(curr->vm->snapshots, snap);
8621
    return 0;
8622 8623
}

8624 8625 8626
typedef struct _testMomentReparentData testMomentReparentData;
typedef testMomentReparentData *testMomentReparentDataPtr;
struct _testMomentReparentData {
8627
    virDomainMomentObjPtr parent;
8628 8629 8630 8631
    virDomainObjPtr vm;
    int err;
};

8632
static int
8633
testDomainMomentReparentChildren(void *payload,
J
Ján Tomko 已提交
8634
                                 const void *name G_GNUC_UNUSED,
8635
                                 void *data)
8636
{
8637 8638
    virDomainMomentObjPtr moment = payload;
    testMomentReparentDataPtr rep = data;
8639

8640
    if (rep->err < 0)
8641
        return 0;
8642

8643
    VIR_FREE(moment->def->parent_name);
8644

8645 8646
    if (rep->parent->def)
        moment->def->parent_name = g_strdup(rep->parent->def->name);
8647

8648
    return 0;
8649 8650 8651 8652 8653 8654 8655
}

static int
testDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
                         unsigned int flags)
{
    virDomainObjPtr vm = NULL;
8656 8657
    virDomainMomentObjPtr snap = NULL;
    virDomainMomentObjPtr parentsnap = NULL;
8658 8659 8660 8661 8662 8663 8664 8665 8666 8667 8668 8669 8670
    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)) {
8671
        testMomentRemoveData rem;
8672 8673
        rem.vm = vm;
        rem.current = false;
8674 8675 8676
        virDomainMomentForEachDescendant(snap,
                                         testDomainSnapshotDiscardAll,
                                         &rem);
8677
        if (rem.current)
8678
            virDomainSnapshotSetCurrent(vm->snapshots, snap);
8679
    } else if (snap->nchildren) {
8680
        testMomentReparentData rep;
8681 8682 8683
        rep.parent = snap->parent;
        rep.vm = vm;
        rep.err = 0;
8684
        virDomainMomentForEachChild(snap,
8685
                                    testDomainMomentReparentChildren,
8686
                                    &rep);
8687 8688 8689
        if (rep.err < 0)
            goto cleanup;

8690
        virDomainMomentMoveChildren(snap, snap->parent);
8691 8692 8693
    }

    if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) {
8694
        virDomainMomentDropChildren(snap);
8695
    } else {
8696
        virDomainMomentDropParent(snap);
8697
        if (snap == virDomainSnapshotGetCurrent(vm->snapshots)) {
8698
            if (snap->def->parent_name) {
8699
                parentsnap = virDomainSnapshotFindByName(vm->snapshots,
8700
                                                         snap->def->parent_name);
8701
                if (!parentsnap)
8702
                    VIR_WARN("missing parent snapshot matching name '%s'",
8703
                             snap->def->parent_name);
8704
            }
8705
            virDomainSnapshotSetCurrent(vm->snapshots, parentsnap);
8706 8707 8708 8709 8710
        }
        virDomainSnapshotObjListRemove(vm->snapshots, snap);
    }

    ret = 0;
8711
 cleanup:
8712
    virDomainObjEndAPI(&vm);
8713 8714 8715 8716 8717 8718 8719
    return ret;
}

static int
testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                           unsigned int flags)
{
8720
    testDriverPtr privconn = snapshot->domain->conn->privateData;
8721
    virDomainObjPtr vm = NULL;
8722
    virDomainMomentObjPtr snap = NULL;
8723 8724
    virObjectEventPtr event = NULL;
    virObjectEventPtr event2 = NULL;
8725
    virDomainDefPtr config = NULL;
8726
    virDomainSnapshotDefPtr snapdef;
8727 8728 8729 8730 8731 8732 8733 8734 8735 8736 8737 8738 8739 8740 8741 8742 8743 8744 8745 8746 8747 8748 8749 8750 8751
    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;
8752
    snapdef = virDomainSnapshotObjGetDef(snap);
8753 8754

    if (!vm->persistent &&
8755 8756
        snapdef->state != VIR_DOMAIN_SNAPSHOT_RUNNING &&
        snapdef->state != VIR_DOMAIN_SNAPSHOT_PAUSED &&
8757 8758 8759 8760 8761 8762 8763 8764 8765
        (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)) {
8766
        if (!snap->def->dom) {
8767 8768
            virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY,
                           _("snapshot '%s' lacks domain '%s' rollback info"),
8769
                           snap->def->name, vm->def->name);
8770 8771 8772
            goto cleanup;
        }
        if (virDomainObjIsActive(vm) &&
8773 8774
            !(snapdef->state == VIR_DOMAIN_SNAPSHOT_RUNNING ||
              snapdef->state == VIR_DOMAIN_SNAPSHOT_PAUSED) &&
8775 8776 8777 8778 8779 8780 8781 8782
            (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;
        }
    }

8783
    virDomainSnapshotSetCurrent(vm->snapshots, NULL);
8784

8785
    config = virDomainDefCopy(snap->def->dom,
8786
                              privconn->xmlopt, NULL, true);
8787 8788 8789
    if (!config)
        goto cleanup;

8790 8791
    if (snapdef->state == VIR_DOMAIN_SNAPSHOT_RUNNING ||
        snapdef->state == VIR_DOMAIN_SNAPSHOT_PAUSED) {
8792 8793 8794 8795 8796 8797 8798
        /* 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.  */
8799 8800
            if (!virDomainDefCheckABIStability(vm->def, config,
                                               privconn->xmlopt)) {
8801 8802 8803 8804 8805 8806 8807 8808 8809 8810 8811 8812 8813
                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);
8814
                event = virDomainEventLifecycleNewFromObj(vm,
8815 8816
                            VIR_DOMAIN_EVENT_STOPPED,
                            VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
8817
                virObjectEventStateQueue(privconn->eventState, event);
8818 8819 8820 8821 8822 8823 8824 8825 8826 8827 8828
                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. */
8829
                event = virDomainEventLifecycleNewFromObj(vm,
8830 8831 8832 8833 8834 8835 8836 8837 8838 8839 8840 8841 8842
                                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;
8843
            event = virDomainEventLifecycleNewFromObj(vm,
8844 8845 8846 8847 8848 8849
                                VIR_DOMAIN_EVENT_STARTED,
                                VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
        }

        /* Touch up domain state.  */
        if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING) &&
8850
            (snapdef->state == VIR_DOMAIN_SNAPSHOT_PAUSED ||
8851 8852 8853 8854 8855 8856
             (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 */
8857
                event2 = virDomainEventLifecycleNewFromObj(vm,
8858 8859 8860 8861 8862
                                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 已提交
8863
            virObjectUnref(event);
8864 8865 8866 8867
            event = NULL;

            if (was_stopped) {
                /* Transition 2 */
8868
                event = virDomainEventLifecycleNewFromObj(vm,
8869 8870 8871 8872
                                VIR_DOMAIN_EVENT_STARTED,
                                VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            } else if (was_running) {
                /* Transition 8 */
8873
                event = virDomainEventLifecycleNewFromObj(vm,
8874 8875 8876 8877 8878 8879 8880 8881 8882 8883 8884 8885
                                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);
8886
            event = virDomainEventLifecycleNewFromObj(vm,
8887 8888 8889 8890 8891 8892 8893 8894 8895
                                    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;

8896
            virObjectEventStateQueue(privconn->eventState, event);
8897
            event = virDomainEventLifecycleNewFromObj(vm,
8898 8899 8900
                            VIR_DOMAIN_EVENT_STARTED,
                            VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT);
            if (paused) {
8901
                event2 = virDomainEventLifecycleNewFromObj(vm,
8902 8903 8904 8905 8906 8907
                                VIR_DOMAIN_EVENT_SUSPENDED,
                                VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
            }
        }
    }

8908
    virDomainSnapshotSetCurrent(vm->snapshots, snap);
8909
    ret = 0;
8910
 cleanup:
8911
    if (event) {
8912 8913
        virObjectEventStateQueue(privconn->eventState, event);
        virObjectEventStateQueue(privconn->eventState, event2);
C
Cole Robinson 已提交
8914
    } else {
C
Cédric Bosdonnat 已提交
8915
        virObjectUnref(event2);
8916
    }
8917
    virDomainObjEndAPI(&vm);
8918 8919 8920 8921

    return ret;
}

8922 8923 8924 8925 8926 8927
/*
 * Checkpoint APIs
 */

static int
testDomainCheckpointDiscardAll(void *payload,
J
Ján Tomko 已提交
8928
                               const void *name G_GNUC_UNUSED,
8929 8930 8931 8932 8933 8934 8935 8936 8937 8938 8939 8940 8941 8942 8943 8944 8945 8946 8947 8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958 8959 8960 8961 8962 8963 8964 8965 8966 8967 8968 8969 8970 8971 8972 8973 8974 8975 8976 8977 8978 8979 8980
                               void *data)
{
    virDomainMomentObjPtr chk = payload;
    testMomentRemoveDataPtr curr = data;

    curr->current |= virDomainCheckpointObjListRemove(curr->vm->checkpoints,
                                                      chk);
    return 0;
}

static virDomainObjPtr
testDomObjFromCheckpoint(virDomainCheckpointPtr checkpoint)
{
    return testDomObjFromDomain(checkpoint->domain);
}

static virDomainMomentObjPtr
testCheckpointObjFromName(virDomainObjPtr vm,
                          const char *name)
{
    virDomainMomentObjPtr chk = NULL;

    chk = virDomainCheckpointFindByName(vm->checkpoints, name);
    if (!chk)
        virReportError(VIR_ERR_NO_DOMAIN_CHECKPOINT,
                       _("no domain checkpoint with matching name '%s'"),
                       name);

    return chk;
}

static virDomainMomentObjPtr
testCheckpointObjFromCheckpoint(virDomainObjPtr vm,
                           virDomainCheckpointPtr checkpoint)
{
    return testCheckpointObjFromName(vm, checkpoint->name);
}

static virDomainCheckpointPtr
testDomainCheckpointCreateXML(virDomainPtr domain,
                              const char *xmlDesc,
                              unsigned int flags)
{
    testDriverPtr privconn = domain->conn->privateData;
    virDomainObjPtr vm = NULL;
    char *xml = NULL;
    virDomainMomentObjPtr chk = NULL;
    virDomainCheckpointPtr checkpoint = NULL;
    virDomainMomentObjPtr current = NULL;
    bool update_current = true;
    bool redefine = flags & VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE;
    unsigned int parse_flags = 0;
8981
    g_autoptr(virDomainCheckpointDef) def = NULL;
8982 8983 8984 8985 8986 8987 8988 8989

    virCheckFlags(VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE |
                  VIR_DOMAIN_CHECKPOINT_CREATE_QUIESCE, NULL);

    if (redefine) {
        parse_flags |= VIR_DOMAIN_CHECKPOINT_PARSE_REDEFINE;
        update_current = false;
    }
8990

8991 8992 8993
    if (!(vm = testDomObjFromDomain(domain)))
        goto cleanup;

8994 8995 8996 8997 8998 8999
    if (virDomainSnapshotObjListNum(vm->snapshots, NULL, 0) > 0) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("cannot create checkpoint while snapshot exists"));
        goto cleanup;
    }

9000 9001 9002 9003 9004 9005
    if (!virDomainObjIsActive(vm)) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("cannot create checkpoint for inactive domain"));
        goto cleanup;
    }

9006
    if (!(def = virDomainCheckpointDefParseString(xmlDesc,
9007
                                                  privconn->xmlopt, NULL,
9008 9009 9010 9011
                                                  parse_flags)))
        goto cleanup;

    if (redefine) {
9012
        if (virDomainCheckpointRedefinePrep(vm, &def, &chk,
9013 9014 9015 9016 9017 9018 9019 9020 9021 9022 9023 9024 9025 9026 9027 9028 9029 9030 9031 9032 9033 9034 9035
                                            privconn->xmlopt,
                                            &update_current) < 0)
            goto cleanup;
    } else {
        if (!(def->parent.dom = virDomainDefCopy(vm->def,
                                                 privconn->xmlopt,
                                                 NULL,
                                                 true)))
            goto cleanup;

        if (virDomainCheckpointAlignDisks(def) < 0)
            goto cleanup;
    }

    if (!chk) {
        if (!(chk = virDomainCheckpointAssignDef(vm->checkpoints, def)))
            goto cleanup;

        def = NULL;
    }

    current = virDomainCheckpointGetCurrent(vm->checkpoints);
    if (current) {
9036 9037
        if (!redefine)
            chk->def->parent_name = g_strdup(current->def->name);
9038 9039 9040 9041 9042 9043 9044 9045 9046 9047 9048 9049 9050 9051 9052 9053 9054 9055 9056 9057 9058 9059 9060 9061 9062 9063 9064 9065 9066 9067 9068 9069 9070 9071 9072 9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084 9085 9086 9087 9088 9089 9090 9091 9092 9093 9094 9095 9096 9097 9098 9099 9100 9101 9102 9103 9104 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118 9119 9120 9121 9122 9123 9124 9125 9126 9127 9128 9129 9130 9131 9132 9133 9134 9135 9136 9137 9138 9139 9140 9141 9142 9143 9144 9145 9146 9147 9148 9149 9150 9151 9152 9153 9154 9155 9156 9157 9158 9159 9160 9161 9162 9163 9164 9165 9166 9167 9168 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182 9183 9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195 9196 9197 9198 9199 9200 9201 9202 9203 9204 9205 9206 9207 9208
        if (update_current)
            virDomainCheckpointSetCurrent(vm->checkpoints, NULL);
    }

    /* actually do the checkpoint - except the test driver has nothing
     * to actually do here */

    /* If we fail after this point, there's not a whole lot we can do;
     * we've successfully created the checkpoint, so we have to go
     * forward the best we can.
     */
    checkpoint = virGetDomainCheckpoint(domain, chk->def->name);

 cleanup:
    if (checkpoint) {
        if (update_current)
            virDomainCheckpointSetCurrent(vm->checkpoints, chk);
        virDomainCheckpointLinkParent(vm->checkpoints, chk);
    } else if (chk) {
        virDomainCheckpointObjListRemove(vm->checkpoints, chk);
    }

    virDomainObjEndAPI(&vm);
    VIR_FREE(xml);
    return checkpoint;
}


static int
testDomainListAllCheckpoints(virDomainPtr domain,
                             virDomainCheckpointPtr **chks,
                             unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int n = -1;

    virCheckFlags(VIR_DOMAIN_CHECKPOINT_LIST_ROOTS |
                  VIR_DOMAIN_CHECKPOINT_LIST_TOPOLOGICAL |
                  VIR_DOMAIN_CHECKPOINT_FILTERS_ALL, -1);

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

    n = virDomainListCheckpoints(vm->checkpoints, NULL, domain, chks, flags);

    virDomainObjEndAPI(&vm);
    return n;
}


static int
testDomainCheckpointListAllChildren(virDomainCheckpointPtr checkpoint,
                                    virDomainCheckpointPtr **chks,
                                    unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainMomentObjPtr chk = NULL;
    int n = -1;

    virCheckFlags(VIR_DOMAIN_CHECKPOINT_LIST_DESCENDANTS |
                  VIR_DOMAIN_CHECKPOINT_LIST_TOPOLOGICAL |
                  VIR_DOMAIN_CHECKPOINT_FILTERS_ALL, -1);

    if (!(vm = testDomObjFromCheckpoint(checkpoint)))
        return -1;

    if (!(chk = testCheckpointObjFromCheckpoint(vm, checkpoint)))
        goto cleanup;

    n = virDomainListCheckpoints(vm->checkpoints, chk, checkpoint->domain,
                                 chks, flags);

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


static virDomainCheckpointPtr
testDomainCheckpointLookupByName(virDomainPtr domain,
                                 const char *name,
                                 unsigned int flags)
{
    virDomainObjPtr vm;
    virDomainMomentObjPtr chk = NULL;
    virDomainCheckpointPtr checkpoint = NULL;

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromDomain(domain)))
        return NULL;

    if (!(chk = testCheckpointObjFromName(vm, name)))
        goto cleanup;

    checkpoint = virGetDomainCheckpoint(domain, chk->def->name);

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


static virDomainCheckpointPtr
testDomainCheckpointGetParent(virDomainCheckpointPtr checkpoint,
                              unsigned int flags)
{
    virDomainObjPtr vm;
    virDomainMomentObjPtr chk = NULL;
    virDomainCheckpointPtr parent = NULL;

    virCheckFlags(0, NULL);

    if (!(vm = testDomObjFromCheckpoint(checkpoint)))
        return NULL;

    if (!(chk = testCheckpointObjFromCheckpoint(vm, checkpoint)))
        goto cleanup;

    if (!chk->def->parent_name) {
        virReportError(VIR_ERR_NO_DOMAIN_CHECKPOINT,
                       _("checkpoint '%s' does not have a parent"),
                       chk->def->name);
        goto cleanup;
    }

    parent = virGetDomainCheckpoint(checkpoint->domain, chk->def->parent_name);

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


static char *
testDomainCheckpointGetXMLDesc(virDomainCheckpointPtr checkpoint,
                               unsigned int flags)
{
    testDriverPtr privconn = checkpoint->domain->conn->privateData;
    virDomainObjPtr vm = NULL;
    char *xml = NULL;
    virDomainMomentObjPtr chk = NULL;
    size_t i;
    virDomainCheckpointDefPtr chkdef;
    unsigned int format_flags;

    virCheckFlags(VIR_DOMAIN_CHECKPOINT_XML_SECURE |
                  VIR_DOMAIN_CHECKPOINT_XML_NO_DOMAIN |
                  VIR_DOMAIN_CHECKPOINT_XML_SIZE, NULL);

    if (!(vm = testDomObjFromCheckpoint(checkpoint)))
        return NULL;

    if (!(chk = testCheckpointObjFromCheckpoint(vm, checkpoint)))
        goto cleanup;
    chkdef = virDomainCheckpointObjGetDef(chk);

    if (flags & VIR_DOMAIN_CHECKPOINT_XML_SIZE) {
        if (virDomainObjCheckActive(vm) < 0)
            goto cleanup;

        for (i = 0; i < chkdef->ndisks; i++) {
            virDomainCheckpointDiskDefPtr disk = &chkdef->disks[i];

            if (disk->type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP)
                continue;
            disk->size = 1024; /* Any number will do... */
        }
    }

    format_flags = virDomainCheckpointFormatConvertXMLFlags(flags);
9209
    xml = virDomainCheckpointDefFormat(chkdef,
9210 9211 9212 9213 9214 9215 9216 9217 9218 9219 9220 9221 9222 9223 9224 9225 9226 9227 9228 9229 9230 9231 9232 9233 9234 9235 9236 9237 9238 9239 9240 9241 9242 9243 9244 9245 9246 9247 9248 9249 9250 9251 9252 9253 9254 9255 9256 9257 9258 9259 9260 9261 9262 9263 9264 9265 9266 9267 9268 9269 9270 9271 9272 9273 9274 9275 9276 9277 9278 9279 9280 9281 9282 9283 9284 9285
                                       privconn->xmlopt, format_flags);

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


static int
testDomainCheckpointDelete(virDomainCheckpointPtr checkpoint,
                           unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;
    virDomainMomentObjPtr chk = NULL;
    virDomainMomentObjPtr parentchk = NULL;

    virCheckFlags(VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN |
                  VIR_DOMAIN_CHECKPOINT_DELETE_METADATA_ONLY |
                  VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN_ONLY, -1);

    if (!(vm = testDomObjFromCheckpoint(checkpoint)))
        return -1;

    if (!(chk = testCheckpointObjFromCheckpoint(vm, checkpoint)))
        goto cleanup;

    if (flags & (VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN |
                 VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN_ONLY)) {
        testMomentRemoveData rem;

        rem.vm = vm;
        rem.current = false;
        virDomainMomentForEachDescendant(chk, testDomainCheckpointDiscardAll,
                                         &rem);
        if (rem.current)
            virDomainCheckpointSetCurrent(vm->checkpoints, chk);
    } else if (chk->nchildren) {
        testMomentReparentData rep;

        rep.parent = chk->parent;
        rep.vm = vm;
        rep.err = 0;
        virDomainMomentForEachChild(chk, testDomainMomentReparentChildren,
                                    &rep);
        if (rep.err < 0)
            goto cleanup;
        virDomainMomentMoveChildren(chk, chk->parent);
    }

    if (flags & VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN_ONLY) {
        virDomainMomentDropChildren(chk);
    } else {
        virDomainMomentDropParent(chk);
        if (chk == virDomainCheckpointGetCurrent(vm->checkpoints)) {
            if (chk->def->parent_name) {
                parentchk = virDomainCheckpointFindByName(vm->checkpoints,
                                                          chk->def->parent_name);
                if (!parentchk)
                    VIR_WARN("missing parent checkpoint matching name '%s'",
                             chk->def->parent_name);
            }
            virDomainCheckpointSetCurrent(vm->checkpoints, parentchk);
        }
        virDomainCheckpointObjListRemove(vm->checkpoints, chk);
    }

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

/*
 * Test driver
 */
9286
static virHypervisorDriver testHypervisorDriver = {
9287
    .name = "Test",
9288 9289 9290
    .connectOpen = testConnectOpen, /* 0.1.1 */
    .connectClose = testConnectClose, /* 0.1.1 */
    .connectGetVersion = testConnectGetVersion, /* 0.1.1 */
9291
    .connectGetHostname = testConnectGetHostname, /* 0.6.3 */
9292
    .connectGetMaxVcpus = testConnectGetMaxVcpus, /* 0.3.2 */
9293
    .nodeGetInfo = testNodeGetInfo, /* 0.1.1 */
9294
    .nodeGetCPUStats = testNodeGetCPUStats, /* 2.3.0 */
9295
    .nodeGetFreeMemory = testNodeGetFreeMemory, /* 2.3.0 */
9296
    .nodeGetFreePages = testNodeGetFreePages, /* 2.3.0 */
9297
    .connectGetCapabilities = testConnectGetCapabilities, /* 0.2.1 */
9298
    .connectGetSysinfo = testConnectGetSysinfo, /* 2.3.0 */
9299
    .connectGetType = testConnectGetType, /* 2.3.0 */
9300
    .connectSupportsFeature = testConnectSupportsFeature, /* 5.6.0 */
9301 9302 9303
    .connectListDomains = testConnectListDomains, /* 0.1.1 */
    .connectNumOfDomains = testConnectNumOfDomains, /* 0.1.1 */
    .connectListAllDomains = testConnectListAllDomains, /* 0.9.13 */
9304
    .domainCreateXML = testDomainCreateXML, /* 0.1.4 */
9305
    .domainCreateXMLWithFiles = testDomainCreateXMLWithFiles, /* 5.7.0 */
9306 9307 9308 9309 9310 9311 9312 9313
    .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 */
9314
    .domainReset = testDomainReset, /* 5.7.0 */
9315
    .domainDestroy = testDomainDestroy, /* 0.1.1 */
9316
    .domainDestroyFlags = testDomainDestroyFlags, /* 4.2.0 */
9317
    .domainGetOSType = testDomainGetOSType, /* 0.1.9 */
9318
    .domainGetLaunchSecurityInfo = testDomainGetLaunchSecurityInfo, /* 5.5.0 */
9319 9320 9321
    .domainGetMaxMemory = testDomainGetMaxMemory, /* 0.1.4 */
    .domainSetMaxMemory = testDomainSetMaxMemory, /* 0.1.1 */
    .domainSetMemory = testDomainSetMemory, /* 0.1.4 */
9322
    .domainSetMemoryStatsPeriod = testDomainSetMemoryStatsPeriod, /* 5.6.0 */
E
Eric Blake 已提交
9323
    .domainSetMemoryFlags = testDomainSetMemoryFlags, /* 5.6.0 */
9324
    .domainGetHostname = testDomainGetHostname, /* 5.5.0 */
9325
    .domainGetInfo = testDomainGetInfo, /* 0.1.1 */
9326
    .domainGetState = testDomainGetState, /* 0.9.2 */
9327
    .domainGetTime = testDomainGetTime, /* 5.4.0 */
9328
    .domainSetTime = testDomainSetTime, /* 5.7.0 */
9329
    .domainSave = testDomainSave, /* 0.3.2 */
9330
    .domainSaveFlags = testDomainSaveFlags, /* 0.9.4 */
9331
    .domainRestore = testDomainRestore, /* 0.3.2 */
9332
    .domainRestoreFlags = testDomainRestoreFlags, /* 0.9.4 */
9333
    .domainSaveImageDefineXML = testDomainSaveImageDefineXML, /* 5.5.0 */
9334
    .domainSaveImageGetXMLDesc = testDomainSaveImageGetXMLDesc, /* 5.5.0 */
9335
    .domainCoreDump = testDomainCoreDump, /* 0.3.2 */
9336
    .domainCoreDumpWithFormat = testDomainCoreDumpWithFormat, /* 1.2.3 */
9337
    .domainSetUserPassword = testDomainSetUserPassword, /* 5.6.0 */
9338
    .domainPinEmulator = testDomainPinEmulator, /* 5.6.0 */
9339
    .domainGetEmulatorPinInfo = testDomainGetEmulatorPinInfo, /* 5.6.0 */
9340
    .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */
9341 9342 9343
    .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */
    .domainGetVcpusFlags = testDomainGetVcpusFlags, /* 0.8.5 */
    .domainPinVcpu = testDomainPinVcpu, /* 0.7.3 */
E
Eric Blake 已提交
9344
    .domainPinVcpuFlags = testDomainPinVcpuFlags, /* 5.6.0 */
9345
    .domainGetVcpus = testDomainGetVcpus, /* 0.7.3 */
9346
    .domainGetVcpuPinInfo = testDomainGetVcpuPinInfo, /* 1.2.18 */
9347 9348
    .domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
    .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
9349
    .domainSetMemoryParameters = testDomainSetMemoryParameters, /* 5.6.0 */
9350
    .domainGetMemoryParameters = testDomainGetMemoryParameters, /* 5.6.0 */
9351
    .domainSetNumaParameters = testDomainSetNumaParameters, /* 5.6.0 */
9352
    .domainGetNumaParameters = testDomainGetNumaParameters, /* 5.6.0 */
9353
    .domainSetInterfaceParameters = testDomainSetInterfaceParameters, /* 5.6.0 */
9354
    .domainGetInterfaceParameters = testDomainGetInterfaceParameters, /* 5.6.0 */
9355
    .domainSetBlockIoTune = testDomainSetBlockIoTune, /* 5.7.0 */
9356
    .domainGetBlockIoTune = testDomainGetBlockIoTune, /* 5.7.0 */
9357 9358
    .connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
    .connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
9359 9360
    .domainCreate = testDomainCreate, /* 0.1.11 */
    .domainCreateWithFlags = testDomainCreateWithFlags, /* 0.8.2 */
9361
    .domainCreateWithFiles = testDomainCreateWithFiles, /* 5.7.0 */
9362
    .domainDefineXML = testDomainDefineXML, /* 0.1.11 */
9363
    .domainDefineXMLFlags = testDomainDefineXMLFlags, /* 1.2.12 */
9364
    .domainUndefine = testDomainUndefine, /* 0.1.11 */
9365
    .domainUndefineFlags = testDomainUndefineFlags, /* 0.9.4 */
9366
    .domainFSFreeze = testDomainFSFreeze, /* 5.7.0 */
9367
    .domainFSThaw = testDomainFSThaw, /* 5.7.0 */
9368
    .domainFSTrim = testDomainFSTrim, /* 5.7.0 */
9369 9370
    .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
    .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
9371
    .domainGetDiskErrors = testDomainGetDiskErrors, /* 5.4.0 */
9372
    .domainGetFSInfo = testDomainGetFSInfo, /* 5.6.0 */
9373
    .domainSetPerfEvents = testDomainSetPerfEvents, /* 5.6.0 */
9374
    .domainGetPerfEvents = testDomainGetPerfEvents, /* 5.6.0 */
9375
    .domainGetSchedulerType = testDomainGetSchedulerType, /* 0.3.2 */
9376 9377 9378 9379
    .domainGetSchedulerParameters = testDomainGetSchedulerParameters, /* 0.3.2 */
    .domainGetSchedulerParametersFlags = testDomainGetSchedulerParametersFlags, /* 0.9.2 */
    .domainSetSchedulerParameters = testDomainSetSchedulerParameters, /* 0.3.2 */
    .domainSetSchedulerParametersFlags = testDomainSetSchedulerParametersFlags, /* 0.9.2 */
9380
    .domainBlockStats = testDomainBlockStats, /* 0.7.0 */
9381
    .domainInterfaceAddresses = testDomainInterfaceAddresses, /* 5.4.0 */
9382 9383
    .domainInterfaceStats = testDomainInterfaceStats, /* 0.7.0 */
    .nodeGetCellsFreeMemory = testNodeGetCellsFreeMemory, /* 0.4.2 */
9384 9385 9386 9387
    .connectDomainEventRegister = testConnectDomainEventRegister, /* 0.6.0 */
    .connectDomainEventDeregister = testConnectDomainEventDeregister, /* 0.6.0 */
    .connectIsEncrypted = testConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = testConnectIsSecure, /* 0.7.3 */
9388 9389 9390
    .domainIsActive = testDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = testDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = testDomainIsUpdated, /* 0.8.6 */
9391 9392 9393
    .connectDomainEventRegisterAny = testConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = testConnectDomainEventDeregisterAny, /* 0.8.0 */
    .connectIsAlive = testConnectIsAlive, /* 0.9.8 */
9394
    .nodeGetCPUMap = testNodeGetCPUMap, /* 1.0.0 */
9395
    .domainRename = testDomainRename, /* 4.1.0 */
9396
    .domainScreenshot = testDomainScreenshot, /* 1.0.5 */
9397
    .domainInjectNMI = testDomainInjectNMI, /* 5.6.0 */
9398
    .domainSendKey = testDomainSendKey, /* 5.5.0 */
9399 9400
    .domainGetMetadata = testDomainGetMetadata, /* 1.1.3 */
    .domainSetMetadata = testDomainSetMetadata, /* 1.1.3 */
9401
    .domainGetCPUStats = testDomainGetCPUStats, /* 5.6.0 */
9402
    .domainSendProcessSignal = testDomainSendProcessSignal, /* 5.5.0 */
9403
    .connectGetCPUModelNames = testConnectGetCPUModelNames, /* 1.1.3 */
9404 9405 9406
    .domainManagedSave = testDomainManagedSave, /* 1.1.4 */
    .domainHasManagedSaveImage = testDomainHasManagedSaveImage, /* 1.1.4 */
    .domainManagedSaveRemove = testDomainManagedSaveRemove, /* 1.1.4 */
9407
    .domainMemoryStats = testDomainMemoryStats, /* 5.7.0 */
9408
    .domainMemoryPeek = testDomainMemoryPeek, /* 5.4.0 */
9409
    .domainGetBlockInfo = testDomainGetBlockInfo, /* 5.7.0 */
9410
    .domainSetLifecycleAction = testDomainSetLifecycleAction, /* 5.7.0 */
9411 9412 9413 9414 9415 9416 9417 9418 9419 9420 9421 9422 9423 9424

    .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 */
9425 9426 9427
    .domainSnapshotCreateXML = testDomainSnapshotCreateXML, /* 1.1.4 */
    .domainRevertToSnapshot = testDomainRevertToSnapshot, /* 1.1.4 */
    .domainSnapshotDelete = testDomainSnapshotDelete, /* 1.1.4 */
9428

E
Eric Blake 已提交
9429
    .connectBaselineCPU = testConnectBaselineCPU, /* 1.2.0 */
9430 9431 9432 9433 9434 9435 9436 9437
    .domainCheckpointCreateXML = testDomainCheckpointCreateXML, /* 5.6.0 */
    .domainCheckpointGetXMLDesc = testDomainCheckpointGetXMLDesc, /* 5.6.0 */

    .domainListAllCheckpoints = testDomainListAllCheckpoints, /* 5.6.0 */
    .domainCheckpointListAllChildren = testDomainCheckpointListAllChildren, /* 5.6.0 */
    .domainCheckpointLookupByName = testDomainCheckpointLookupByName, /* 5.6.0 */
    .domainCheckpointGetParent = testDomainCheckpointGetParent, /* 5.6.0 */
    .domainCheckpointDelete = testDomainCheckpointDelete, /* 5.6.0 */
9438 9439 9440
};

static virNetworkDriver testNetworkDriver = {
9441 9442 9443 9444 9445
    .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 */
9446 9447
    .connectNetworkEventRegisterAny = testConnectNetworkEventRegisterAny, /* 1.2.1 */
    .connectNetworkEventDeregisterAny = testConnectNetworkEventDeregisterAny, /* 1.2.1 */
9448 9449 9450 9451
    .networkLookupByUUID = testNetworkLookupByUUID, /* 0.3.2 */
    .networkLookupByName = testNetworkLookupByName, /* 0.3.2 */
    .networkCreateXML = testNetworkCreateXML, /* 0.3.2 */
    .networkDefineXML = testNetworkDefineXML, /* 0.3.2 */
9452
    .networkUndefine = testNetworkUndefine, /* 0.3.2 */
9453
    .networkUpdate = testNetworkUpdate, /* 0.10.2 */
9454
    .networkCreate = testNetworkCreate, /* 0.3.2 */
9455 9456 9457 9458 9459 9460 9461
    .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 */
9462 9463
};

L
Laine Stump 已提交
9464
static virInterfaceDriver testInterfaceDriver = {
9465 9466 9467 9468
    .connectNumOfInterfaces = testConnectNumOfInterfaces, /* 0.7.0 */
    .connectListInterfaces = testConnectListInterfaces, /* 0.7.0 */
    .connectNumOfDefinedInterfaces = testConnectNumOfDefinedInterfaces, /* 0.7.0 */
    .connectListDefinedInterfaces = testConnectListDefinedInterfaces, /* 0.7.0 */
9469
    .connectListAllInterfaces = testConnectListAllInterfaces, /* 4.6.0 */
9470 9471
    .interfaceLookupByName = testInterfaceLookupByName, /* 0.7.0 */
    .interfaceLookupByMACString = testInterfaceLookupByMACString, /* 0.7.0 */
9472 9473 9474 9475 9476 9477
    .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 */
9478 9479 9480
    .interfaceChangeBegin = testInterfaceChangeBegin,   /* 0.9.2 */
    .interfaceChangeCommit = testInterfaceChangeCommit,  /* 0.9.2 */
    .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */
L
Laine Stump 已提交
9481 9482 9483
};


9484
static virStorageDriver testStorageDriver = {
9485 9486 9487 9488 9489 9490
    .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 */
9491 9492
    .connectStoragePoolEventRegisterAny = testConnectStoragePoolEventRegisterAny, /* 2.0.0 */
    .connectStoragePoolEventDeregisterAny = testConnectStoragePoolEventDeregisterAny, /* 2.0.0 */
9493 9494 9495
    .storagePoolLookupByName = testStoragePoolLookupByName, /* 0.5.0 */
    .storagePoolLookupByUUID = testStoragePoolLookupByUUID, /* 0.5.0 */
    .storagePoolLookupByVolume = testStoragePoolLookupByVolume, /* 0.5.0 */
9496 9497
    .storagePoolCreateXML = testStoragePoolCreateXML, /* 0.5.0 */
    .storagePoolDefineXML = testStoragePoolDefineXML, /* 0.5.0 */
9498 9499
    .storagePoolBuild = testStoragePoolBuild, /* 0.5.0 */
    .storagePoolUndefine = testStoragePoolUndefine, /* 0.5.0 */
9500
    .storagePoolCreate = testStoragePoolCreate, /* 0.5.0 */
9501 9502 9503 9504 9505 9506 9507
    .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 */
9508
    .storagePoolNumOfVolumes = testStoragePoolNumOfVolumes, /* 0.5.0 */
9509 9510 9511
    .storagePoolListVolumes = testStoragePoolListVolumes, /* 0.5.0 */
    .storagePoolListAllVolumes = testStoragePoolListAllVolumes, /* 0.10.2 */

9512 9513 9514 9515 9516 9517 9518 9519 9520
    .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 */
9521 9522
    .storagePoolIsActive = testStoragePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = testStoragePoolIsPersistent, /* 0.7.3 */
9523 9524
};

9525
static virNodeDeviceDriver testNodeDeviceDriver = {
9526
    .connectListAllNodeDevices = testConnectListAllNodeDevices, /* 4.1.0 */
9527 9528
    .connectNodeDeviceEventRegisterAny = testConnectNodeDeviceEventRegisterAny, /* 2.2.0 */
    .connectNodeDeviceEventDeregisterAny = testConnectNodeDeviceEventDeregisterAny, /* 2.2.0 */
9529 9530 9531 9532 9533 9534 9535 9536 9537
    .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 */
9538 9539
};

9540
static virConnectDriver testConnectDriver = {
9541
    .localOnly = true,
9542
    .uriSchemes = (const char *[]){ "test", NULL },
9543 9544 9545 9546 9547 9548 9549
    .hypervisorDriver = &testHypervisorDriver,
    .interfaceDriver = &testInterfaceDriver,
    .networkDriver = &testNetworkDriver,
    .nodeDeviceDriver = &testNodeDeviceDriver,
    .nwfilterDriver = NULL,
    .secretDriver = NULL,
    .storageDriver = &testStorageDriver,
9550 9551
};

9552 9553 9554 9555 9556 9557 9558 9559
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
9560 9561
    return virRegisterConnectDriver(&testConnectDriver,
                                    false);
9562
}