test_driver.c 154.1 KB
Newer Older
1 2 3
/*
 * test.c: A "mock" hypervisor for use by application unit tests
 *
E
Eric Blake 已提交
4
 * Copyright (C) 2006-2011 Red Hat, Inc.
5
 * Copyright (C) 2006 Daniel P. Berrange
6
 *
7 8 9 10 11 12 13 14 15 16 17 18 19
 * 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
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
20 21 22 23
 *
 * Daniel Berrange <berrange@redhat.com>
 */

24
#include <config.h>
25

26 27 28
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
29 30
#include <fcntl.h>
#include <unistd.h>
31
#include <sys/stat.h>
C
Cole Robinson 已提交
32
#include <libxml/xmlsave.h>
33

34 35

#include "virterror_internal.h"
36
#include "datatypes.h"
37
#include "test_driver.h"
38
#include "buf.h"
39
#include "util.h"
40
#include "uuid.h"
41
#include "capabilities.h"
42
#include "memory.h"
43
#include "network_conf.h"
L
Laine Stump 已提交
44
#include "interface_conf.h"
45
#include "domain_conf.h"
46 47
#include "domain_event.h"
#include "event.h"
C
Cole Robinson 已提交
48
#include "storage_conf.h"
49
#include "node_device_conf.h"
50
#include "xml.h"
51
#include "threads.h"
52
#include "logging.h"
53
#include "files.h"
54

55 56
#define VIR_FROM_THIS VIR_FROM_TEST

57 58 59 60 61 62 63 64 65
/* Driver specific info to carry with a domain */
struct _testDomainObjPrivate {
    virVcpuInfoPtr vcpu_infos;

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

66 67 68 69 70 71 72 73 74 75 76
#define MAX_CPUS 128

struct _testCell {
    unsigned long mem;
    int numCpus;
    int cpus[MAX_CPUS];
};
typedef struct _testCell testCell;
typedef struct _testCell *testCellPtr;

#define MAX_CELLS 128
77

78
struct _testConn {
79
    virMutex lock;
80

81 82
    char path[PATH_MAX];
    int nextDomID;
83
    virCapsPtr caps;
84
    virNodeInfo nodeInfo;
85
    virDomainObjList domains;
86
    virNetworkObjList networks;
L
Laine Stump 已提交
87
    virInterfaceObjList ifaces;
C
Cole Robinson 已提交
88
    virStoragePoolObjList pools;
89
    virNodeDeviceObjList devs;
90 91
    int numCells;
    testCell cells[MAX_CELLS];
92 93 94 95 96 97 98


    /* An array of callbacks */
    virDomainEventCallbackListPtr domainEventCallbacks;
    virDomainEventQueuePtr domainEventQueue;
    int domainEventTimer;
    int domainEventDispatching;
99 100 101
};
typedef struct _testConn testConn;
typedef struct _testConn *testConnPtr;
102

103
#define TEST_MODEL "i686"
104
#define TEST_MODEL_WORDSIZE 32
105
#define TEST_EMULATOR "/usr/bin/test-hv"
106

107
static const virNodeInfo defaultNodeInfo = {
108
    TEST_MODEL,
109 110 111 112 113 114 115
    1024*1024*3, /* 3 GB */
    16,
    1400,
    2,
    2,
    2,
    2,
116 117
};

118

119 120 121
#define testError(code, ...)                                      \
        virReportErrorHelper(NULL, VIR_FROM_TEST, code, __FILE__, \
                             __FUNCTION__, __LINE__, __VA_ARGS__)
122

123 124 125 126 127 128
static int testClose(virConnectPtr conn);
static void testDomainEventFlush(int timer, void *opaque);
static void testDomainEventQueue(testConnPtr driver,
                                 virDomainEventPtr event);


129 130
static void testDriverLock(testConnPtr driver)
{
131
    virMutexLock(&driver->lock);
132 133 134 135
}

static void testDriverUnlock(testConnPtr driver)
{
136
    virMutexUnlock(&driver->lock);
137 138
}

139 140 141 142 143 144 145 146 147 148 149 150 151 152
static void *testDomainObjPrivateAlloc(void)
{
    testDomainObjPrivatePtr priv;

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

    return priv;
}

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

D
Daniel P. Berrange 已提交
153
    VIR_FREE(priv->vcpu_infos);
154 155 156 157 158
    VIR_FREE(priv->cpumaps);
    VIR_FREE(priv);
}


159 160
static virCapsPtr
testBuildCapabilities(virConnectPtr conn) {
161
    testConnPtr privconn = conn->privateData;
162 163 164 165
    virCapsPtr caps;
    virCapsGuestPtr guest;
    const char *const guest_types[] = { "hvm", "xen" };
    int i;
166

167 168
    if ((caps = virCapabilitiesNew(TEST_MODEL, 0, 0)) == NULL)
        goto no_memory;
169

170 171 172 173
    if (virCapabilitiesAddHostFeature(caps, "pae") < 0)
        goto no_memory;
    if (virCapabilitiesAddHostFeature(caps ,"nonpae") < 0)
        goto no_memory;
174

175 176 177 178
    for (i = 0; i < privconn->numCells; i++) {
        if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].numCpus,
                                           privconn->cells[i].cpus) < 0)
            goto no_memory;
179 180
    }

181 182 183 184 185 186 187 188 189 190
    for (i = 0; i < ARRAY_CARDINALITY(guest_types) ; i++) {
        if ((guest = virCapabilitiesAddGuest(caps,
                                             guest_types[i],
                                             TEST_MODEL,
                                             TEST_MODEL_WORDSIZE,
                                             TEST_EMULATOR,
                                             NULL,
                                             0,
                                             NULL)) == NULL)
            goto no_memory;
191

192 193 194 195 196 197 198
        if (virCapabilitiesAddGuestDomain(guest,
                                          "test",
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
            goto no_memory;
199

200 201 202 203
        if (virCapabilitiesAddGuestFeature(guest, "pae", 1, 1) == NULL)
            goto no_memory;
        if (virCapabilitiesAddGuestFeature(guest ,"nonpae", 1, 1) == NULL)
            goto no_memory;
204 205
    }

206 207 208
    caps->privateDataAllocFunc = testDomainObjPrivateAlloc;
    caps->privateDataFreeFunc = testDomainObjPrivateFree;

209 210 211 212 213 214 215 216
    caps->host.secModel.model = strdup("testSecurity");
    if (!caps->host.secModel.model)
        goto no_memory;

    caps->host.secModel.doi = strdup("");
    if (!caps->host.secModel.doi)
        goto no_memory;

217
    return caps;
218

219
no_memory:
220
    virReportOOMError();
221 222
    virCapabilitiesFree(caps);
    return NULL;
223 224
}

225

226 227 228 229 230 231 232 233 234 235
static const char *defaultDomainXML =
"<domain type='test'>"
"  <name>test</name>"
"  <memory>8388608</memory>"
"  <currentMemory>2097152</currentMemory>"
"  <vcpu>2</vcpu>"
"  <os>"
"    <type>hvm</type>"
"  </os>"
"</domain>";
236 237


238 239 240 241 242 243 244 245 246 247 248
static const char *defaultNetworkXML =
"<network>"
"  <name>default</name>"
"  <bridge name='virbr0' />"
"  <forward/>"
"  <ip address='192.168.122.1' netmask='255.255.255.0'>"
"    <dhcp>"
"      <range start='192.168.122.2' end='192.168.122.254' />"
"    </dhcp>"
"  </ip>"
"</network>";
249

L
Laine Stump 已提交
250 251 252 253 254 255 256 257 258 259 260
static const char *defaultInterfaceXML =
"<interface type=\"ethernet\" name=\"eth1\">"
"  <start mode=\"onboot\"/>"
"  <mac address=\"aa:bb:cc:dd:ee:ff\"/>"
"  <mtu size=\"1492\"/>"
"  <protocol family=\"ipv4\">"
"    <ip address=\"192.168.0.5\" prefix=\"24\"/>"
"    <route gateway=\"192.168.0.1\"/>"
"  </protocol>"
"</interface>";

C
Cole Robinson 已提交
261 262 263 264 265 266 267 268
static const char *defaultPoolXML =
"<pool type='dir'>"
"  <name>default-pool</name>"
"  <target>"
"    <path>/default-pool</path>"
"  </target>"
"</pool>";

269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
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";

292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
static const char *defaultNodeXML =
"<device>"
"  <name>computer</name>"
"  <capability type='system'>"
"    <hardware>"
"      <vendor>Libvirt</vendor>"
"      <version>Test driver</version>"
"      <serial>123456</serial>"
"      <uuid>11111111-2222-3333-4444-555555555555</uuid>"
"    </hardware>"
"    <firmware>"
"      <vendor>Libvirt</vendor>"
"      <version>Test Driver</version>"
"      <release_date>01/22/2007</release_date>"
"    </firmware>"
"  </capability>"
"</device>";

310
static const unsigned long long defaultPoolCap = (100 * 1024 * 1024 * 1024ull);
C
Cole Robinson 已提交
311 312
static const unsigned long long defaultPoolAlloc = 0;

313
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool);
314
static int testNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
315

316
static char *
317
testDomainGenerateIfname(virDomainDefPtr domdef) {
318 319 320 321 322 323 324 325
    int maxif = 1024;
    int ifctr, i;

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

        if (virAsprintf(&ifname, "testnet%d", ifctr) < 0) {
326
            virReportOOMError();
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
            return NULL;
        }

        /* Generate network interface names */
        for (i = 0 ; i < domdef->nnets ; i++) {
            if (domdef->nets[i]->ifname &&
                STREQ (domdef->nets[i]->ifname, ifname)) {
                found = 1;
                break;
            }
        }

        if (!found)
            return ifname;
    }

343
    testError(VIR_ERR_INTERNAL_ERROR,
344 345 346 347
              _("Exceeded max iface limit %d"), maxif);
    return NULL;
}

348
static int
349
testDomainGenerateIfnames(virDomainDefPtr domdef)
350 351 352 353 354 355 356 357
{
    int i = 0;

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

358
        ifname = testDomainGenerateIfname(domdef);
359
        if (!ifname)
360
            return -1;
361 362 363 364

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

365
    return 0;
366 367
}

368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
/* Helper to update info for a single VCPU */
static int
testDomainUpdateVCPU(virConnectPtr conn ATTRIBUTE_UNUSED,
                     virDomainObjPtr dom,
                     int vcpu,
                     int maplen,
                     int maxcpu)
{
    testDomainObjPrivatePtr privdata = dom->privateData;
    virVcpuInfoPtr info = &privdata->vcpu_infos[vcpu];
    unsigned char *cpumap = VIR_GET_CPUMAP(privdata->cpumaps, maplen, vcpu);
    int j;

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

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

    if (dom->def->cpumask) {
        for (j = 0; j < maxcpu && j < VIR_DOMAIN_CPUMASK_LEN; ++j) {
            if (dom->def->cpumask[j]) {
                VIR_USE_CPU(cpumap, j);
                info->cpu = j;
            }
        }
    } else {
        for (j = 0; j < maxcpu; ++j) {
            if ((j % 3) == 0) {
                /* Mark of every third CPU as usable */
                VIR_USE_CPU(cpumap, j);
                info->cpu = j;
            }
        }
    }

    return 0;
}

/*
 * Update domain VCPU amount and info
 *
 * @conn: virConnectPtr
 * @dom : domain needing updates
 * @nvcpus: New amount of vcpus for the domain
 * @clear_all: If true, rebuild info for ALL vcpus, not just newly added vcpus
 */
static int
testDomainUpdateVCPUs(virConnectPtr conn,
                      virDomainObjPtr dom,
                      int nvcpus,
                      unsigned int clear_all)
{
    testConnPtr privconn = conn->privateData;
    testDomainObjPrivatePtr privdata = dom->privateData;
    int i, ret = -1;
    int cpumaplen, maxcpu;

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

    if (VIR_REALLOC_N(privdata->vcpu_infos, nvcpus) < 0) {
432
        virReportOOMError();
433 434 435 436
        goto cleanup;
    }

    if (VIR_REALLOC_N(privdata->cpumaps, nvcpus * cpumaplen) < 0) {
437
        virReportOOMError();
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
        goto cleanup;
    }

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

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

454
    dom->def->vcpus = nvcpus;
455 456 457 458 459
    ret = 0;
cleanup:
    return ret;
}

460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
static void
testDomainShutdownState(virDomainPtr domain,
                        virDomainObjPtr privdom)
{
    if (privdom->newDef) {
        virDomainDefFree(privdom->def);
        privdom->def = privdom->newDef;
        privdom->newDef = NULL;
    }

    privdom->state = VIR_DOMAIN_SHUTOFF;
    privdom->def->id = -1;
    if (domain)
        domain->id = -1;
}

476
/* Set up domain runtime state */
477 478 479 480 481
static int
testDomainStartState(virConnectPtr conn,
                     virDomainObjPtr dom)
{
    testConnPtr privconn = conn->privateData;
482
    int ret = -1;
483

484 485 486
    if (testDomainUpdateVCPUs(conn, dom, dom->def->vcpus, 1) < 0)
        goto cleanup;

487 488 489
    dom->state = VIR_DOMAIN_RUNNING;
    dom->def->id = privconn->nextDomID++;

490
    if (virDomainObjSetDefTransient(privconn->caps, dom, false) < 0) {
491 492 493
        goto cleanup;
    }

494 495
    ret = 0;
cleanup:
496 497
    if (ret < 0)
        testDomainShutdownState(NULL, dom);
498
    return ret;
499
}
500

501
static int testOpenDefault(virConnectPtr conn) {
502 503
    int u;
    struct timeval tv;
504
    testConnPtr privconn;
505 506 507 508
    virDomainDefPtr domdef = NULL;
    virDomainObjPtr domobj = NULL;
    virNetworkDefPtr netdef = NULL;
    virNetworkObjPtr netobj = NULL;
L
Laine Stump 已提交
509 510
    virInterfaceDefPtr interfacedef = NULL;
    virInterfaceObjPtr interfaceobj = NULL;
C
Cole Robinson 已提交
511 512
    virStoragePoolDefPtr pooldef = NULL;
    virStoragePoolObjPtr poolobj = NULL;
513 514
    virNodeDeviceDefPtr nodedef = NULL;
    virNodeDeviceObjPtr nodeobj = NULL;
515

516
    if (VIR_ALLOC(privconn) < 0) {
517
        virReportOOMError();
518 519
        return VIR_DRV_OPEN_ERROR;
    }
520
    if (virMutexInit(&privconn->lock) < 0) {
521
        testError(VIR_ERR_INTERNAL_ERROR,
522 523 524 525 526
                  "%s", _("cannot initialize mutex"));
        VIR_FREE(privconn);
        return VIR_DRV_OPEN_ERROR;
    }

527
    testDriverLock(privconn);
528
    conn->privateData = privconn;
529 530

    if (gettimeofday(&tv, NULL) < 0) {
531
        virReportSystemError(errno,
532
                             "%s", _("getting time of day"));
533
        goto error;
534 535
    }

536 537 538
    if (virDomainObjListInit(&privconn->domains) < 0)
        goto error;

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

541
    /* Numa setup */
542 543 544 545 546 547 548 549 550
    privconn->numCells = 2;
    for (u = 0; u < 2; ++u) {
        privconn->cells[u].numCpus = 8;
        privconn->cells[u].mem = (u + 1) * 2048 * 1024;
    }
    for (u = 0 ; u < 16 ; u++) {
        privconn->cells[u % 2].cpus[(u / 2)] = u;
    }

551 552 553 554 555
    if (!(privconn->caps = testBuildCapabilities(conn)))
        goto error;

    privconn->nextDomID = 1;

556
    if (!(domdef = virDomainDefParseString(privconn->caps,
557 558
                                           defaultDomainXML,
                                           VIR_DOMAIN_XML_INACTIVE)))
559
        goto error;
560
    if (testDomainGenerateIfnames(domdef) < 0)
561
        goto error;
562
    if (!(domobj = virDomainAssignDef(privconn->caps,
563
                                      &privconn->domains, domdef, false)))
564 565
        goto error;
    domdef = NULL;
566

567
    domobj->persistent = 1;
568 569 570 571 572
    if (testDomainStartState(conn, domobj) < 0) {
        virDomainObjUnlock(domobj);
        goto error;
    }

573
    virDomainObjUnlock(domobj);
574

575
    if (!(netdef = virNetworkDefParseString(defaultNetworkXML)))
576
        goto error;
577
    if (!(netobj = virNetworkAssignDef(&privconn->networks, netdef))) {
578 579 580 581 582
        virNetworkDefFree(netdef);
        goto error;
    }
    netobj->active = 1;
    netobj->persistent = 1;
583
    virNetworkObjUnlock(netobj);
584

585
    if (!(interfacedef = virInterfaceDefParseString(defaultInterfaceXML)))
L
Laine Stump 已提交
586
        goto error;
587
    if (!(interfaceobj = virInterfaceAssignDef(&privconn->ifaces, interfacedef))) {
L
Laine Stump 已提交
588 589 590 591 592 593
        virInterfaceDefFree(interfacedef);
        goto error;
    }
    interfaceobj->active = 1;
    virInterfaceObjUnlock(interfaceobj);

594
    if (!(pooldef = virStoragePoolDefParseString(defaultPoolXML)))
C
Cole Robinson 已提交
595 596
        goto error;

597
    if (!(poolobj = virStoragePoolObjAssignDef(&privconn->pools,
C
Cole Robinson 已提交
598 599 600 601
                                               pooldef))) {
        virStoragePoolDefFree(pooldef);
        goto error;
    }
602

603
    if (testStoragePoolObjSetDefaults(poolobj) == -1) {
604
        virStoragePoolObjUnlock(poolobj);
C
Cole Robinson 已提交
605
        goto error;
606
    }
C
Cole Robinson 已提交
607
    poolobj->active = 1;
608
    virStoragePoolObjUnlock(poolobj);
C
Cole Robinson 已提交
609

610
    /* Init default node device */
611
    if (!(nodedef = virNodeDeviceDefParseString(defaultNodeXML, 0)))
612
        goto error;
613
    if (!(nodeobj = virNodeDeviceAssignDef(&privconn->devs,
614 615 616 617 618 619
                                           nodedef))) {
        virNodeDeviceDefFree(nodedef);
        goto error;
    }
    virNodeDeviceObjUnlock(nodeobj);

620
    testDriverUnlock(privconn);
621

622 623 624
    return VIR_DRV_OPEN_SUCCESS;

error:
625
    virDomainObjListDeinit(&privconn->domains);
626
    virNetworkObjListFree(&privconn->networks);
L
Laine Stump 已提交
627
    virInterfaceObjListFree(&privconn->ifaces);
C
Cole Robinson 已提交
628
    virStoragePoolObjListFree(&privconn->pools);
629
    virNodeDeviceObjListFree(&privconn->devs);
630
    virCapabilitiesFree(privconn->caps);
631
    testDriverUnlock(privconn);
632
    conn->privateData = NULL;
633
    VIR_FREE(privconn);
634
    virDomainDefFree(domdef);
635
    return VIR_DRV_OPEN_ERROR;
636 637 638 639
}


static char *testBuildFilename(const char *relativeTo,
640 641 642 643 644 645 646 647
                               const char *filename) {
    char *offset;
    int baseLen;
    if (!filename || filename[0] == '\0')
        return (NULL);
    if (filename[0] == '/')
        return strdup(filename);

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

665
static int testOpenVolumesForPool(xmlDocPtr xml,
666 667 668 669 670 671 672
                                  xmlXPathContextPtr ctxt,
                                  const char *file,
                                  virStoragePoolObjPtr pool,
                                  int poolidx) {
    char *vol_xpath;
    int i, ret, func_ret = -1;
    xmlNodePtr *vols = NULL;
673
    virStorageVolDefPtr def = NULL;
674 675 676

    /* Find storage volumes */
    if (virAsprintf(&vol_xpath, "/node/pool[%d]/volume", poolidx) < 0) {
677
        virReportOOMError();
678 679 680
        goto error;
    }

681
    ret = virXPathNodeSet(vol_xpath, ctxt, &vols);
682 683
    VIR_FREE(vol_xpath);
    if (ret < 0) {
684
        testError(VIR_ERR_XML_ERROR,
685 686 687 688 689 690 691 692 693 694
                  _("node vol list for pool '%s'"), pool->def->name);
        goto error;
    }

    for (i = 0 ; i < ret ; i++) {
        char *relFile = virXMLPropString(vols[i], "file");
        if (relFile != NULL) {
            char *absFile = testBuildFilename(file, relFile);
            VIR_FREE(relFile);
            if (!absFile) {
695
                testError(VIR_ERR_INTERNAL_ERROR, "%s",
696 697 698 699
                          _("resolving volume filename"));
                goto error;
            }

700
            def = virStorageVolDefParseFile(pool->def, absFile);
701 702 703 704
            VIR_FREE(absFile);
            if (!def)
                goto error;
        } else {
705
            if ((def = virStorageVolDefParseNode(pool->def, xml,
706 707 708 709 710 711 712
                                                 vols[i])) == NULL) {
                goto error;
            }
        }

        if (VIR_REALLOC_N(pool->volumes.objs,
                          pool->volumes.count+1) < 0) {
713
            virReportOOMError();
714 715 716
            goto error;
        }

717 718 719 720 721 722 723
        if (def->target.path == NULL) {
            if (virAsprintf(&def->target.path, "%s/%s",
                            pool->def->target.path,
                            def->name) == -1) {
                virReportOOMError();
                goto error;
            }
724 725 726
        }

        if (def->key == NULL) {
727 728 729 730 731
            def->key = strdup(def->target.path);
            if (def->key == NULL) {
                virReportOOMError();
                goto error;
            }
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
        }

        pool->def->allocation += def->allocation;
        pool->def->available = (pool->def->capacity -
                                pool->def->allocation);

        pool->volumes.objs[pool->volumes.count++] = def;
        def = NULL;
    }

    func_ret = 0;
error:
    virStorageVolDefFree(def);
    VIR_FREE(vols);
    return func_ret;
}

749
static int testOpenFromFile(virConnectPtr conn,
750
                            const char *file) {
751
    int fd = -1, i, ret;
752 753
    long l;
    char *str;
754
    xmlDocPtr xml = NULL;
755
    xmlNodePtr root = NULL;
756 757
    xmlNodePtr *domains = NULL, *networks = NULL, *ifaces = NULL,
               *pools = NULL, *devs = NULL;
758 759
    xmlXPathContextPtr ctxt = NULL;
    virNodeInfoPtr nodeInfo;
760
    virNetworkObjPtr net;
L
Laine Stump 已提交
761
    virInterfaceObjPtr iface;
762
    virDomainObjPtr dom;
763 764
    testConnPtr privconn;
    if (VIR_ALLOC(privconn) < 0) {
765
        virReportOOMError();
766 767
        return VIR_DRV_OPEN_ERROR;
    }
768
    if (virMutexInit(&privconn->lock) < 0) {
769
        testError(VIR_ERR_INTERNAL_ERROR,
770 771 772 773 774
                  "%s", _("cannot initialize mutex"));
        VIR_FREE(privconn);
        return VIR_DRV_OPEN_ERROR;
    }

775
    testDriverLock(privconn);
776
    conn->privateData = privconn;
777

778 779 780
    if (virDomainObjListInit(&privconn->domains) < 0)
        goto error;

781 782
    if (!(privconn->caps = testBuildCapabilities(conn)))
        goto error;
783 784

    if ((fd = open(file, O_RDONLY)) < 0) {
785
        virReportSystemError(errno,
786 787
                             _("loading host definition file '%s'"),
                             file);
788
        goto error;
789 790
    }

791 792 793
    if (!(xml = xmlReadFd(fd, file, NULL,
                          XML_PARSE_NOENT | XML_PARSE_NONET |
                          XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
794
        testError(VIR_ERR_INTERNAL_ERROR,
795
                  _("Invalid XML in file '%s'"), file);
796
        goto error;
797
    }
798
    VIR_FORCE_CLOSE(fd);
799

800 801
    root = xmlDocGetRootElement(xml);
    if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "node"))) {
802
        testError(VIR_ERR_XML_ERROR, "%s",
803
                  _("Root element is not 'node'"));
804
        goto error;
805 806
    }

807 808
    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
809
        testError(VIR_ERR_INTERNAL_ERROR, "%s",
C
Cole Robinson 已提交
810
                  _("creating xpath context"));
811
        goto error;
812
    }
813

814
    privconn->nextDomID = 1;
815
    privconn->numCells = 0;
C
Chris Lalancette 已提交
816
    if (virStrcpyStatic(privconn->path, file) == NULL) {
817
        testError(VIR_ERR_INTERNAL_ERROR,
C
Chris Lalancette 已提交
818 819 820
                  _("Path %s too big for destination"), file);
        goto error;
    }
821 822 823
    memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));

    nodeInfo = &privconn->nodeInfo;
824
    ret = virXPathLong("string(/node/cpu/nodes[1])", ctxt, &l);
825 826 827
    if (ret == 0) {
        nodeInfo->nodes = l;
    } else if (ret == -2) {
828
        testError(VIR_ERR_XML_ERROR, "%s", _("node cpu numa nodes"));
829
        goto error;
830
    }
831

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

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

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

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

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

885
    ret = virXPathLong("string(/node/memory[1])", ctxt, &l);
886 887 888
    if (ret == 0) {
        nodeInfo->memory = l;
    } else if (ret == -2) {
889
        testError(VIR_ERR_XML_ERROR, "%s", _("node memory"));
890
        goto error;
891
    }
892

893
    ret = virXPathNodeSet("/node/domain", ctxt, &domains);
894
    if (ret < 0) {
895
        testError(VIR_ERR_XML_ERROR, "%s", _("node domain list"));
896
        goto error;
897
    }
898

899
    for (i = 0 ; i < ret ; i++) {
900 901 902 903 904 905
        virDomainDefPtr def;
        char *relFile = virXMLPropString(domains[i], "file");
        if (relFile != NULL) {
            char *absFile = testBuildFilename(file, relFile);
            VIR_FREE(relFile);
            if (!absFile) {
906
                testError(VIR_ERR_INTERNAL_ERROR, "%s", _("resolving domain filename"));
907 908
                goto error;
            }
909
            def = virDomainDefParseFile(privconn->caps, absFile,
910
                                        VIR_DOMAIN_XML_INACTIVE);
911
            VIR_FREE(absFile);
912 913 914
            if (!def)
                goto error;
        } else {
915 916
            if ((def = virDomainDefParseNode(privconn->caps, xml, domains[i],
                                             VIR_DOMAIN_XML_INACTIVE)) == NULL)
917 918 919
                goto error;
        }

920
        if (testDomainGenerateIfnames(def) < 0 ||
921
            !(dom = virDomainAssignDef(privconn->caps,
922
                                       &privconn->domains, def, false))) {
923
            virDomainDefFree(def);
924 925
            goto error;
        }
926

927
        dom->persistent = 1;
928 929 930 931 932
        if (testDomainStartState(conn, dom) < 0) {
            virDomainObjUnlock(dom);
            goto error;
        }

933
        virDomainObjUnlock(dom);
934
    }
935
    VIR_FREE(domains);
936

937
    ret = virXPathNodeSet("/node/network", ctxt, &networks);
938
    if (ret < 0) {
939
        testError(VIR_ERR_XML_ERROR, "%s", _("node network list"));
940 941 942 943 944 945 946 947
        goto error;
    }
    for (i = 0 ; i < ret ; i++) {
        virNetworkDefPtr def;
        char *relFile = virXMLPropString(networks[i], "file");
        if (relFile != NULL) {
            char *absFile = testBuildFilename(file, relFile);
            VIR_FREE(relFile);
948
            if (!absFile) {
949
                testError(VIR_ERR_INTERNAL_ERROR, "%s", _("resolving network filename"));
950 951
                goto error;
            }
952

953
            def = virNetworkDefParseFile(absFile);
954
            VIR_FREE(absFile);
955 956 957
            if (!def)
                goto error;
        } else {
958
            if ((def = virNetworkDefParseNode(xml, networks[i])) == NULL)
959
                goto error;
960
        }
961
        if (!(net = virNetworkAssignDef(&privconn->networks,
962 963 964
                                        def))) {
            virNetworkDefFree(def);
            goto error;
965
        }
966
        net->persistent = 1;
967
        net->active = 1;
968
        virNetworkObjUnlock(net);
969
    }
970
    VIR_FREE(networks);
971

L
Laine Stump 已提交
972
    /* Parse interface definitions */
973
    ret = virXPathNodeSet("/node/interface", ctxt, &ifaces);
L
Laine Stump 已提交
974
    if (ret < 0) {
975
        testError(VIR_ERR_XML_ERROR, "%s", _("node interface list"));
L
Laine Stump 已提交
976 977 978 979 980 981 982 983 984
        goto error;
    }
    for (i = 0 ; i < ret ; i++) {
        virInterfaceDefPtr def;
        char *relFile = virXMLPropString(ifaces[i], "file");
        if (relFile != NULL) {
            char *absFile = testBuildFilename(file, relFile);
            VIR_FREE(relFile);
            if (!absFile) {
985
                testError(VIR_ERR_INTERNAL_ERROR, "%s", _("resolving interface filename"));
L
Laine Stump 已提交
986 987 988
                goto error;
            }

989
            def = virInterfaceDefParseFile(absFile);
L
Laine Stump 已提交
990 991 992 993
            VIR_FREE(absFile);
            if (!def)
                goto error;
        } else {
994
            if ((def = virInterfaceDefParseNode(xml, ifaces[i])) == NULL)
L
Laine Stump 已提交
995 996
                goto error;
        }
997

998
        if (!(iface = virInterfaceAssignDef(&privconn->ifaces, def))) {
L
Laine Stump 已提交
999 1000 1001
            virInterfaceDefFree(def);
            goto error;
        }
1002 1003

        iface->active = 1;
L
Laine Stump 已提交
1004 1005 1006 1007
        virInterfaceObjUnlock(iface);
    }
    VIR_FREE(ifaces);

C
Cole Robinson 已提交
1008
    /* Parse Storage Pool list */
1009
    ret = virXPathNodeSet("/node/pool", ctxt, &pools);
C
Cole Robinson 已提交
1010
    if (ret < 0) {
1011
        testError(VIR_ERR_XML_ERROR, "%s", _("node pool list"));
C
Cole Robinson 已提交
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
        goto error;
    }
    for (i = 0 ; i < ret ; i++) {
        virStoragePoolDefPtr def;
        virStoragePoolObjPtr pool;
        char *relFile = virXMLPropString(pools[i], "file");
        if (relFile != NULL) {
            char *absFile = testBuildFilename(file, relFile);
            VIR_FREE(relFile);
            if (!absFile) {
1022
                testError(VIR_ERR_INTERNAL_ERROR, "%s",
C
Cole Robinson 已提交
1023 1024 1025 1026
                          _("resolving pool filename"));
                goto error;
            }

1027
            def = virStoragePoolDefParseFile(absFile);
C
Cole Robinson 已提交
1028 1029 1030 1031
            VIR_FREE(absFile);
            if (!def)
                goto error;
        } else {
1032
            if ((def = virStoragePoolDefParseNode(xml,
1033
                                                  pools[i])) == NULL) {
C
Cole Robinson 已提交
1034 1035 1036 1037
                goto error;
            }
        }

1038
        if (!(pool = virStoragePoolObjAssignDef(&privconn->pools,
C
Cole Robinson 已提交
1039 1040 1041 1042 1043
                                                def))) {
            virStoragePoolDefFree(def);
            goto error;
        }

1044
        if (testStoragePoolObjSetDefaults(pool) == -1) {
1045
            virStoragePoolObjUnlock(pool);
C
Cole Robinson 已提交
1046
            goto error;
1047
        }
C
Cole Robinson 已提交
1048
        pool->active = 1;
1049 1050

        /* Find storage volumes */
1051
        if (testOpenVolumesForPool(xml, ctxt, file, pool, i+1) < 0) {
1052 1053 1054 1055
            virStoragePoolObjUnlock(pool);
            goto error;
        }

1056
        virStoragePoolObjUnlock(pool);
C
Cole Robinson 已提交
1057
    }
1058
    VIR_FREE(pools);
C
Cole Robinson 已提交
1059

1060
    ret = virXPathNodeSet("/node/device", ctxt, &devs);
1061
    if (ret < 0) {
1062
        testError(VIR_ERR_XML_ERROR, "%s", _("node device list"));
1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074
        goto error;
    }
    for (i = 0 ; i < ret ; i++) {
        virNodeDeviceDefPtr def;
        virNodeDeviceObjPtr dev;
        char *relFile = virXMLPropString(devs[i], "file");

        if (relFile != NULL) {
            char *absFile = testBuildFilename(file, relFile);
            VIR_FREE(relFile);

            if (!absFile) {
1075
                testError(VIR_ERR_INTERNAL_ERROR, "%s",
1076 1077 1078 1079
                          _("resolving device filename"));
                goto error;
            }

1080
            def = virNodeDeviceDefParseFile(absFile, 0);
1081 1082 1083 1084
            VIR_FREE(absFile);
            if (!def)
                goto error;
        } else {
1085
            if ((def = virNodeDeviceDefParseNode(xml, devs[i], 0)) == NULL)
1086 1087
                goto error;
        }
1088
        if (!(dev = virNodeDeviceAssignDef(&privconn->devs, def))) {
1089 1090 1091 1092 1093 1094 1095 1096
            virNodeDeviceDefFree(def);
            goto error;
        }
        virNodeDeviceObjUnlock(dev);
    }
    VIR_FREE(devs);


J
Jim Meyering 已提交
1097
    xmlXPathFreeContext(ctxt);
1098
    xmlFreeDoc(xml);
1099
    testDriverUnlock(privconn);
1100

1101
    return (0);
1102 1103

 error:
J
Jim Meyering 已提交
1104
    xmlXPathFreeContext(ctxt);
1105
    xmlFreeDoc(xml);
1106 1107
    VIR_FREE(domains);
    VIR_FREE(networks);
L
Laine Stump 已提交
1108
    VIR_FREE(ifaces);
C
Cole Robinson 已提交
1109
    VIR_FREE(pools);
1110
    VIR_FORCE_CLOSE(fd);
1111
    virDomainObjListDeinit(&privconn->domains);
1112
    virNetworkObjListFree(&privconn->networks);
L
Laine Stump 已提交
1113
    virInterfaceObjListFree(&privconn->ifaces);
C
Cole Robinson 已提交
1114
    virStoragePoolObjListFree(&privconn->pools);
1115
    testDriverUnlock(privconn);
1116
    VIR_FREE(privconn);
1117
    conn->privateData = NULL;
1118
    return VIR_DRV_OPEN_ERROR;
1119 1120
}

1121

1122
static virDrvOpenStatus testOpen(virConnectPtr conn,
1123
                    virConnectAuthPtr auth ATTRIBUTE_UNUSED,
1124
                    int flags ATTRIBUTE_UNUSED)
1125
{
1126
    int ret;
1127

1128
    if (!conn->uri)
1129
        return VIR_DRV_OPEN_DECLINED;
1130

1131
    if (!conn->uri->scheme || STRNEQ(conn->uri->scheme, "test"))
1132
        return VIR_DRV_OPEN_DECLINED;
1133

1134
    /* Remote driver should handle these. */
1135
    if (conn->uri->server)
1136 1137
        return VIR_DRV_OPEN_DECLINED;

1138
    /* From this point on, the connection is for us. */
1139 1140 1141
    if (!conn->uri->path
        || conn->uri->path[0] == '\0'
        || (conn->uri->path[0] == '/' && conn->uri->path[1] == '\0')) {
1142 1143
        testError(VIR_ERR_INVALID_ARG,
                  "%s", _("testOpen: supply a path or use test:///default"));
1144 1145
        return VIR_DRV_OPEN_ERROR;
    }
1146

1147
    if (STREQ(conn->uri->path, "/default"))
1148 1149
        ret = testOpenDefault(conn);
    else
1150
        ret = testOpenFromFile(conn,
1151
                               conn->uri->path);
1152

1153 1154
    if (ret == VIR_DRV_OPEN_SUCCESS) {
        testConnPtr privconn = conn->privateData;
1155
        testDriverLock(privconn);
1156 1157 1158
        /* Init callback list */
        if (VIR_ALLOC(privconn->domainEventCallbacks) < 0 ||
            !(privconn->domainEventQueue = virDomainEventQueueNew())) {
1159
            virReportOOMError();
1160
            testDriverUnlock(privconn);
1161 1162 1163 1164 1165 1166
            testClose(conn);
            return VIR_DRV_OPEN_ERROR;
        }

        if ((privconn->domainEventTimer =
             virEventAddTimeout(-1, testDomainEventFlush, privconn, NULL)) < 0)
1167
            VIR_DEBUG0("virEventAddTimeout failed: No addTimeoutImpl defined. "
1168
                   "continuing without events.");
1169
        testDriverUnlock(privconn);
1170 1171
    }

1172
    return (ret);
1173 1174
}

1175
static int testClose(virConnectPtr conn)
1176
{
1177
    testConnPtr privconn = conn->privateData;
1178
    testDriverLock(privconn);
1179
    virCapabilitiesFree(privconn->caps);
1180
    virDomainObjListDeinit(&privconn->domains);
D
Daniel P. Berrange 已提交
1181
    virNodeDeviceObjListFree(&privconn->devs);
1182
    virNetworkObjListFree(&privconn->networks);
L
Laine Stump 已提交
1183
    virInterfaceObjListFree(&privconn->ifaces);
C
Cole Robinson 已提交
1184
    virStoragePoolObjListFree(&privconn->pools);
1185 1186 1187 1188 1189 1190 1191

    virDomainEventCallbackListFree(privconn->domainEventCallbacks);
    virDomainEventQueueFree(privconn->domainEventQueue);

    if (privconn->domainEventTimer != -1)
        virEventRemoveTimeout(privconn->domainEventTimer);

1192
    testDriverUnlock(privconn);
1193
    virMutexDestroy(&privconn->lock);
1194

1195
    VIR_FREE (privconn);
1196
    conn->privateData = NULL;
1197
    return 0;
1198 1199
}

1200 1201
static int testGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
                          unsigned long *hvVer)
1202
{
1203 1204
    *hvVer = 2;
    return (0);
1205 1206
}

1207 1208 1209 1210 1211 1212 1213 1214 1215 1216
static int testIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return 1;
}

static int testIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return 0;
}

1217 1218 1219 1220 1221 1222 1223 1224
static int testGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED,
                           const char *type ATTRIBUTE_UNUSED)
{
    return 32;
}

static int testNodeGetInfo(virConnectPtr conn,
                           virNodeInfoPtr info)
1225
{
1226
    testConnPtr privconn = conn->privateData;
1227
    testDriverLock(privconn);
1228
    memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo));
1229
    testDriverUnlock(privconn);
1230
    return (0);
1231 1232
}

1233
static char *testGetCapabilities (virConnectPtr conn)
1234
{
1235
    testConnPtr privconn = conn->privateData;
1236
    char *xml;
1237
    testDriverLock(privconn);
1238
    if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL)
1239
        virReportOOMError();
1240
    testDriverUnlock(privconn);
1241
    return xml;
1242 1243
}

1244
static int testNumOfDomains(virConnectPtr conn)
1245
{
1246
    testConnPtr privconn = conn->privateData;
1247
    int count;
1248

1249
    testDriverLock(privconn);
1250
    count = virDomainObjListNumOfDomains(&privconn->domains, 1);
1251
    testDriverUnlock(privconn);
1252

1253
    return count;
1254 1255
}

1256 1257 1258 1259 1260 1261 1262 1263 1264 1265
static int testDomainIsActive(virDomainPtr dom)
{
    testConnPtr privconn = dom->conn->privateData;
    virDomainObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virDomainFindByUUID(&privconn->domains, dom->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
1266
        testError(VIR_ERR_NO_DOMAIN, NULL);
1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286
        goto cleanup;
    }
    ret = virDomainObjIsActive(obj);

cleanup:
    if (obj)
        virDomainObjUnlock(obj);
    return ret;
}

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

    testDriverLock(privconn);
    obj = virDomainFindByUUID(&privconn->domains, dom->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
1287
        testError(VIR_ERR_NO_DOMAIN, NULL);
1288 1289 1290 1291 1292 1293 1294 1295 1296 1297
        goto cleanup;
    }
    ret = obj->persistent;

cleanup:
    if (obj)
        virDomainObjUnlock(obj);
    return ret;
}

1298 1299 1300 1301 1302
static int testDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
{
    return 0;
}

1303
static virDomainPtr
1304
testDomainCreateXML(virConnectPtr conn, const char *xml,
1305
                      unsigned int flags)
1306
{
1307
    testConnPtr privconn = conn->privateData;
1308
    virDomainPtr ret = NULL;
1309
    virDomainDefPtr def;
1310
    virDomainObjPtr dom = NULL;
1311
    virDomainEventPtr event = NULL;
1312

1313 1314
    virCheckFlags(0, NULL);

1315
    testDriverLock(privconn);
1316
    if ((def = virDomainDefParseString(privconn->caps, xml,
1317
                                       VIR_DOMAIN_XML_INACTIVE)) == NULL)
1318
        goto cleanup;
1319

1320 1321 1322
    if (virDomainObjIsDuplicate(&privconn->domains, def, 1) < 0)
        goto cleanup;

1323
    if (testDomainGenerateIfnames(def) < 0)
1324
        goto cleanup;
1325
    if (!(dom = virDomainAssignDef(privconn->caps,
1326
                                   &privconn->domains, def, false)))
1327 1328
        goto cleanup;
    def = NULL;
1329 1330 1331

    if (testDomainStartState(conn, dom) < 0)
        goto cleanup;
1332

1333 1334 1335 1336
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);

1337
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1338
    if (ret)
1339
        ret->id = dom->def->id;
1340 1341

cleanup:
1342 1343
    if (dom)
        virDomainObjUnlock(dom);
1344 1345
    if (event)
        testDomainEventQueue(privconn, event);
1346
    virDomainDefFree(def);
1347
    testDriverUnlock(privconn);
1348
    return ret;
1349 1350 1351
}


1352 1353
static virDomainPtr testLookupDomainByID(virConnectPtr conn,
                                         int id)
1354
{
1355
    testConnPtr privconn = conn->privateData;
1356 1357
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1358

1359 1360 1361 1362 1363
    testDriverLock(privconn);
    dom = virDomainFindByID(&privconn->domains, id);
    testDriverUnlock(privconn);

    if (dom == NULL) {
1364
        testError(VIR_ERR_NO_DOMAIN, NULL);
1365
        goto cleanup;
1366 1367
    }

1368
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1369 1370 1371 1372
    if (ret)
        ret->id = dom->def->id;

cleanup:
1373 1374
    if (dom)
        virDomainObjUnlock(dom);
1375
    return ret;
1376 1377
}

1378 1379
static virDomainPtr testLookupDomainByUUID(virConnectPtr conn,
                                           const unsigned char *uuid)
1380
{
1381
    testConnPtr privconn = conn->privateData;
1382 1383
    virDomainPtr ret = NULL;
    virDomainObjPtr dom ;
1384

1385 1386 1387 1388 1389
    testDriverLock(privconn);
    dom = virDomainFindByUUID(&privconn->domains, uuid);
    testDriverUnlock(privconn);

    if (dom == NULL) {
1390
        testError(VIR_ERR_NO_DOMAIN, NULL);
1391
        goto cleanup;
1392
    }
1393

1394
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1395 1396 1397 1398
    if (ret)
        ret->id = dom->def->id;

cleanup:
1399 1400
    if (dom)
        virDomainObjUnlock(dom);
1401
    return ret;
1402 1403
}

1404 1405
static virDomainPtr testLookupDomainByName(virConnectPtr conn,
                                           const char *name)
1406
{
1407
    testConnPtr privconn = conn->privateData;
1408 1409
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;
1410

1411 1412 1413 1414 1415
    testDriverLock(privconn);
    dom = virDomainFindByName(&privconn->domains, name);
    testDriverUnlock(privconn);

    if (dom == NULL) {
1416
        testError(VIR_ERR_NO_DOMAIN, NULL);
1417
        goto cleanup;
1418
    }
1419

1420
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
1421 1422 1423 1424
    if (ret)
        ret->id = dom->def->id;

cleanup:
1425 1426
    if (dom)
        virDomainObjUnlock(dom);
1427
    return ret;
1428 1429
}

1430 1431 1432
static int testListDomains (virConnectPtr conn,
                            int *ids,
                            int maxids)
1433
{
1434
    testConnPtr privconn = conn->privateData;
1435
    int n;
1436

1437
    testDriverLock(privconn);
1438
    n = virDomainObjListGetActiveIDs(&privconn->domains, ids, maxids);
1439
    testDriverUnlock(privconn);
1440

1441
    return n;
1442 1443
}

1444
static int testDestroyDomain (virDomainPtr domain)
1445
{
1446 1447
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1448
    virDomainEventPtr event = NULL;
1449
    int ret = -1;
1450

1451
    testDriverLock(privconn);
1452 1453 1454 1455
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
1456
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1457
        goto cleanup;
1458
    }
1459

1460
    testDomainShutdownState(domain, privdom);
1461 1462 1463
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
1464

1465 1466 1467
    if (!privdom->persistent) {
        virDomainRemoveInactive(&privconn->domains,
                                privdom);
1468
        privdom = NULL;
1469
    }
1470 1471 1472

    ret = 0;
cleanup:
1473 1474
    if (privdom)
        virDomainObjUnlock(privdom);
1475 1476
    if (event)
        testDomainEventQueue(privconn, event);
1477
    testDriverUnlock(privconn);
1478
    return ret;
1479 1480
}

1481
static int testResumeDomain (virDomainPtr domain)
1482
{
1483 1484
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1485
    virDomainEventPtr event = NULL;
1486
    int ret = -1;
1487

1488
    testDriverLock(privconn);
1489 1490
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1491
    testDriverUnlock(privconn);
1492 1493

    if (privdom == NULL) {
1494
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1495
        goto cleanup;
1496
    }
1497

1498
    if (privdom->state != VIR_DOMAIN_PAUSED) {
1499
        testError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"),
1500
                  domain->name);
1501
        goto cleanup;
1502
    }
1503

1504
    privdom->state = VIR_DOMAIN_RUNNING;
1505 1506 1507
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_RESUMED,
                                     VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
1508 1509 1510
    ret = 0;

cleanup:
1511 1512
    if (privdom)
        virDomainObjUnlock(privdom);
1513 1514 1515 1516 1517
    if (event) {
        testDriverLock(privconn);
        testDomainEventQueue(privconn, event);
        testDriverUnlock(privconn);
    }
1518
    return ret;
1519 1520
}

1521
static int testPauseDomain (virDomainPtr domain)
1522
{
1523 1524
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1525
    virDomainEventPtr event = NULL;
1526
    int ret = -1;
1527

1528
    testDriverLock(privconn);
1529 1530
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1531
    testDriverUnlock(privconn);
1532 1533

    if (privdom == NULL) {
1534
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1535
        goto cleanup;
1536
    }
1537

1538 1539
    if (privdom->state == VIR_DOMAIN_SHUTOFF ||
        privdom->state == VIR_DOMAIN_PAUSED) {
1540
        testError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"),
1541
                  domain->name);
1542
        goto cleanup;
1543
    }
1544

1545
    privdom->state = VIR_DOMAIN_PAUSED;
1546 1547 1548
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_SUSPENDED,
                                     VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
1549 1550 1551
    ret = 0;

cleanup:
1552 1553
    if (privdom)
        virDomainObjUnlock(privdom);
1554 1555 1556 1557 1558 1559

    if (event) {
        testDriverLock(privconn);
        testDomainEventQueue(privconn, event);
        testDriverUnlock(privconn);
    }
1560
    return ret;
1561 1562
}

1563
static int testShutdownDomain (virDomainPtr domain)
1564
{
1565 1566
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1567
    virDomainEventPtr event = NULL;
1568
    int ret = -1;
1569

1570
    testDriverLock(privconn);
1571 1572 1573 1574
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
1575
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1576
        goto cleanup;
1577
    }
1578

1579
    if (privdom->state == VIR_DOMAIN_SHUTOFF) {
1580
        testError(VIR_ERR_INTERNAL_ERROR,
1581
                  _("domain '%s' not running"), domain->name);
1582
        goto cleanup;
1583
    }
1584

1585
    testDomainShutdownState(domain, privdom);
1586 1587 1588
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1589

1590 1591 1592 1593 1594
    if (!privdom->persistent) {
        virDomainRemoveInactive(&privconn->domains,
                                privdom);
        privdom = NULL;
    }
1595

1596
    ret = 0;
1597
cleanup:
1598 1599
    if (privdom)
        virDomainObjUnlock(privdom);
1600 1601
    if (event)
        testDomainEventQueue(privconn, event);
1602
    testDriverUnlock(privconn);
1603
    return ret;
1604 1605 1606
}

/* Similar behaviour as shutdown */
1607 1608
static int testRebootDomain (virDomainPtr domain,
                             unsigned int action ATTRIBUTE_UNUSED)
1609
{
1610 1611
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1612
    virDomainEventPtr event = NULL;
1613
    int ret = -1;
1614

1615
    testDriverLock(privconn);
1616 1617 1618 1619
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
1620
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1621
        goto cleanup;
1622
    }
1623

1624 1625 1626 1627
    privdom->state = VIR_DOMAIN_SHUTDOWN;
    switch (privdom->def->onReboot) {
    case VIR_DOMAIN_LIFECYCLE_DESTROY:
        privdom->state = VIR_DOMAIN_SHUTOFF;
1628 1629
        break;

1630 1631
    case VIR_DOMAIN_LIFECYCLE_RESTART:
        privdom->state = VIR_DOMAIN_RUNNING;
1632 1633
        break;

1634 1635
    case VIR_DOMAIN_LIFECYCLE_PRESERVE:
        privdom->state = VIR_DOMAIN_SHUTOFF;
1636 1637
        break;

1638 1639
    case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME:
        privdom->state = VIR_DOMAIN_RUNNING;
1640
        break;
1641

1642
    default:
1643
        privdom->state = VIR_DOMAIN_SHUTOFF;
1644 1645
        break;
    }
1646

1647
    if (privdom->state == VIR_DOMAIN_SHUTOFF) {
1648
        testDomainShutdownState(domain, privdom);
1649 1650 1651
        event = virDomainEventNewFromObj(privdom,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
1652

1653 1654 1655 1656 1657
        if (!privdom->persistent) {
            virDomainRemoveInactive(&privconn->domains,
                                    privdom);
            privdom = NULL;
        }
1658 1659
    }

1660 1661
    ret = 0;
cleanup:
1662 1663
    if (privdom)
        virDomainObjUnlock(privdom);
1664 1665
    if (event)
        testDomainEventQueue(privconn, event);
1666
    testDriverUnlock(privconn);
1667
    return ret;
1668 1669
}

1670 1671
static int testGetDomainInfo (virDomainPtr domain,
                              virDomainInfoPtr info)
1672
{
1673
    testConnPtr privconn = domain->conn->privateData;
1674
    struct timeval tv;
1675
    virDomainObjPtr privdom;
1676
    int ret = -1;
1677

1678
    testDriverLock(privconn);
1679 1680
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1681
    testDriverUnlock(privconn);
1682 1683

    if (privdom == NULL) {
1684
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1685
        goto cleanup;
1686
    }
1687 1688

    if (gettimeofday(&tv, NULL) < 0) {
1689
        testError(VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1690
                  "%s", _("getting time of day"));
1691
        goto cleanup;
1692 1693
    }

1694
    info->state = privdom->state;
1695 1696
    info->memory = privdom->def->mem.cur_balloon;
    info->maxMem = privdom->def->mem.max_balloon;
1697 1698
    info->nrVirtCpu = privdom->def->vcpus;
    info->cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
1699 1700 1701
    ret = 0;

cleanup:
1702 1703
    if (privdom)
        virDomainObjUnlock(privdom);
1704
    return ret;
1705 1706
}

1707 1708 1709 1710 1711
#define TEST_SAVE_MAGIC "TestGuestMagic"

static int testDomainSave(virDomainPtr domain,
                          const char *path)
{
1712
    testConnPtr privconn = domain->conn->privateData;
1713 1714 1715
    char *xml = NULL;
    int fd = -1;
    int len;
1716
    virDomainObjPtr privdom;
1717
    virDomainEventPtr event = NULL;
1718
    int ret = -1;
1719

1720
    testDriverLock(privconn);
1721 1722 1723 1724
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
1725
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1726
        goto cleanup;
1727
    }
1728

1729
    xml = virDomainDefFormat(privdom->def,
C
Cole Robinson 已提交
1730 1731
                             VIR_DOMAIN_XML_SECURE);

1732
    if (xml == NULL) {
1733
        virReportSystemError(errno,
1734 1735
                             _("saving domain '%s' failed to allocate space for metadata"),
                             domain->name);
1736
        goto cleanup;
1737
    }
1738 1739

    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
1740
        virReportSystemError(errno,
1741 1742
                             _("saving domain '%s' to '%s': open failed"),
                             domain->name, path);
1743
        goto cleanup;
1744
    }
1745
    len = strlen(xml);
1746
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
1747
        virReportSystemError(errno,
1748 1749
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1750
        goto cleanup;
1751
    }
1752
    if (safewrite(fd, (char*)&len, sizeof(len)) < 0) {
1753
        virReportSystemError(errno,
1754 1755
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1756
        goto cleanup;
1757
    }
1758
    if (safewrite(fd, xml, len) < 0) {
1759
        virReportSystemError(errno,
1760 1761
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1762
        goto cleanup;
1763
    }
1764

1765
    if (VIR_CLOSE(fd) < 0) {
1766
        virReportSystemError(errno,
1767 1768
                             _("saving domain '%s' to '%s': write failed"),
                             domain->name, path);
1769
        goto cleanup;
1770
    }
1771 1772
    fd = -1;

1773
    testDomainShutdownState(domain, privdom);
1774 1775 1776
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
1777

1778 1779 1780
    if (!privdom->persistent) {
        virDomainRemoveInactive(&privconn->domains,
                                privdom);
1781
        privdom = NULL;
1782
    }
1783

1784
    ret = 0;
1785 1786 1787 1788 1789 1790 1791
cleanup:
    VIR_FREE(xml);

    /* Don't report failure in close or unlink, because
     * in either case we're already in a failure scenario
     * and have reported a earlier error */
    if (ret != 0) {
1792
        VIR_FORCE_CLOSE(fd);
1793 1794
        unlink(path);
    }
1795 1796
    if (privdom)
        virDomainObjUnlock(privdom);
1797 1798
    if (event)
        testDomainEventQueue(privconn, event);
1799
    testDriverUnlock(privconn);
1800
    return ret;
1801 1802
}

1803 1804
static int testDomainRestore(virConnectPtr conn,
                             const char *path)
1805
{
1806
    testConnPtr privconn = conn->privateData;
1807
    char *xml = NULL;
1808
    char magic[15];
1809 1810 1811
    int fd = -1;
    int len;
    virDomainDefPtr def = NULL;
1812
    virDomainObjPtr dom = NULL;
1813
    virDomainEventPtr event = NULL;
1814
    int ret = -1;
1815 1816

    if ((fd = open(path, O_RDONLY)) < 0) {
1817
        virReportSystemError(errno,
1818 1819
                             _("cannot read domain image '%s'"),
                             path);
1820
        goto cleanup;
1821
    }
1822
    if (saferead(fd, magic, sizeof(magic)) != sizeof(magic)) {
1823
        virReportSystemError(errno,
1824 1825
                             _("incomplete save header in '%s'"),
                             path);
1826
        goto cleanup;
1827
    }
1828
    if (memcmp(magic, TEST_SAVE_MAGIC, sizeof(magic))) {
1829
        testError(VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1830
                  "%s", _("mismatched header magic"));
1831
        goto cleanup;
1832
    }
1833
    if (saferead(fd, (char*)&len, sizeof(len)) != sizeof(len)) {
1834
        virReportSystemError(errno,
1835 1836
                             _("failed to read metadata length in '%s'"),
                             path);
1837
        goto cleanup;
1838 1839
    }
    if (len < 1 || len > 8192) {
1840
        testError(VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1841
                  "%s", _("length of metadata out of range"));
1842
        goto cleanup;
1843
    }
1844
    if (VIR_ALLOC_N(xml, len+1) < 0) {
1845
        virReportOOMError();
1846
        goto cleanup;
1847
    }
1848
    if (saferead(fd, xml, len) != len) {
1849
        virReportSystemError(errno,
1850
                             _("incomplete metdata in '%s'"), path);
1851
        goto cleanup;
1852 1853
    }
    xml[len] = '\0';
1854

1855
    testDriverLock(privconn);
1856
    def = virDomainDefParseString(privconn->caps, xml,
1857
                                  VIR_DOMAIN_XML_INACTIVE);
1858
    if (!def)
1859
        goto cleanup;
1860

1861 1862 1863
    if (virDomainObjIsDuplicate(&privconn->domains, def, 1) < 0)
        goto cleanup;

1864
    if (testDomainGenerateIfnames(def) < 0)
1865
        goto cleanup;
1866
    if (!(dom = virDomainAssignDef(privconn->caps,
1867
                                   &privconn->domains, def, true)))
1868 1869
        goto cleanup;
    def = NULL;
1870

1871 1872 1873
    if (testDomainStartState(conn, dom) < 0)
        goto cleanup;

1874 1875 1876
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
1877
    ret = 0;
1878 1879 1880 1881

cleanup:
    virDomainDefFree(def);
    VIR_FREE(xml);
1882
    VIR_FORCE_CLOSE(fd);
1883 1884
    if (dom)
        virDomainObjUnlock(dom);
1885 1886
    if (event)
        testDomainEventQueue(privconn, event);
1887
    testDriverUnlock(privconn);
1888
    return ret;
1889 1890
}

1891 1892 1893
static int testDomainCoreDump(virDomainPtr domain,
                              const char *to,
                              int flags ATTRIBUTE_UNUSED)
1894
{
1895
    testConnPtr privconn = domain->conn->privateData;
1896
    int fd = -1;
1897
    virDomainObjPtr privdom;
1898
    virDomainEventPtr event = NULL;
1899
    int ret = -1;
1900

1901
    testDriverLock(privconn);
1902 1903 1904 1905
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
1906
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1907
        goto cleanup;
1908
    }
1909 1910

    if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
1911
        virReportSystemError(errno,
1912 1913
                             _("domain '%s' coredump: failed to open %s"),
                             domain->name, to);
1914
        goto cleanup;
1915
    }
1916
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
1917
        virReportSystemError(errno,
1918 1919
                             _("domain '%s' coredump: failed to write header to %s"),
                             domain->name, to);
1920
        goto cleanup;
1921
    }
1922
    if (VIR_CLOSE(fd) < 0) {
1923
        virReportSystemError(errno,
1924 1925
                             _("domain '%s' coredump: write failed: %s"),
                             domain->name, to);
1926
        goto cleanup;
1927
    }
1928

1929 1930 1931 1932 1933 1934 1935 1936 1937 1938
    if (flags & VIR_DUMP_CRASH) {
        testDomainShutdownState(domain, privdom);
        event = virDomainEventNewFromObj(privdom,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
        if (!privdom->persistent) {
            virDomainRemoveInactive(&privconn->domains,
                                    privdom);
            privdom = NULL;
        }
1939
    }
1940

1941
    ret = 0;
1942
cleanup:
1943
    VIR_FORCE_CLOSE(fd);
1944 1945
    if (privdom)
        virDomainObjUnlock(privdom);
1946 1947
    if (event)
        testDomainEventQueue(privconn, event);
1948
    testDriverUnlock(privconn);
1949
    return ret;
1950 1951
}

1952
static char *testGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) {
1953 1954
    char *ret = strdup("linux");
    if (!ret)
1955
        virReportOOMError();
1956
    return ret;
1957 1958 1959
}

static unsigned long testGetMaxMemory(virDomainPtr domain) {
1960 1961
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1962
    unsigned long ret = 0;
1963

1964
    testDriverLock(privconn);
1965 1966
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1967
    testDriverUnlock(privconn);
1968 1969

    if (privdom == NULL) {
1970
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1971
        goto cleanup;
1972
    }
1973

1974
    ret = privdom->def->mem.max_balloon;
1975 1976

cleanup:
1977 1978
    if (privdom)
        virDomainObjUnlock(privdom);
1979
    return ret;
1980 1981 1982 1983 1984
}

static int testSetMaxMemory(virDomainPtr domain,
                            unsigned long memory)
{
1985 1986
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
1987
    int ret = -1;
1988

1989
    testDriverLock(privconn);
1990 1991
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
1992
    testDriverUnlock(privconn);
1993 1994

    if (privdom == NULL) {
1995
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
1996
        goto cleanup;
1997
    }
1998 1999

    /* XXX validate not over host memory wrt to other domains */
2000
    privdom->def->mem.max_balloon = memory;
2001 2002 2003
    ret = 0;

cleanup:
2004 2005
    if (privdom)
        virDomainObjUnlock(privdom);
2006
    return ret;
2007 2008
}

2009 2010 2011
static int testSetMemory(virDomainPtr domain,
                         unsigned long memory)
{
2012 2013
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2014
    int ret = -1;
2015

2016
    testDriverLock(privconn);
2017 2018
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
2019
    testDriverUnlock(privconn);
2020 2021

    if (privdom == NULL) {
2022
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2023
        goto cleanup;
2024
    }
2025

2026
    if (memory > privdom->def->mem.max_balloon) {
2027
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2028
        goto cleanup;
2029
    }
2030

2031
    privdom->def->mem.cur_balloon = memory;
2032 2033 2034
    ret = 0;

cleanup:
2035 2036
    if (privdom)
        virDomainObjUnlock(privdom);
2037
    return ret;
2038 2039
}

2040 2041
static int
testDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
C
Cole Robinson 已提交
2042
{
2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr vm;
    virDomainDefPtr def;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
                  VIR_DOMAIN_VCPU_CONFIG |
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

    /* Exactly one of LIVE or CONFIG must be set.  */
    if (!(flags & VIR_DOMAIN_VCPU_LIVE) == !(flags & VIR_DOMAIN_VCPU_CONFIG)) {
        testError(VIR_ERR_INVALID_ARG,
                  _("invalid flag combination: (0x%x)"), flags);
2056 2057 2058
        return -1;
    }

2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087
    testDriverLock(privconn);
    vm = virDomainFindByUUID(&privconn->domains, domain->uuid);
    testDriverUnlock(privconn);

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

    if (flags & VIR_DOMAIN_VCPU_LIVE) {
        if (!virDomainObjIsActive(vm)) {
            testError(VIR_ERR_OPERATION_INVALID, "%s",
                      _("domain not active"));
            goto cleanup;
        }
        def = vm->def;
    } else {
        def = vm->newDef ? vm->newDef : vm->def;
    }

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

cleanup:
    if (vm)
        virDomainObjUnlock(vm);
    return ret;
C
Cole Robinson 已提交
2088 2089
}

2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100
static int
testDomainGetMaxVcpus(virDomainPtr domain)
{
    return testDomainGetVcpusFlags(domain, (VIR_DOMAIN_VCPU_LIVE |
                                            VIR_DOMAIN_VCPU_MAXIMUM));
}

static int
testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
                        unsigned int flags)
{
2101
    testConnPtr privconn = domain->conn->privateData;
2102
    virDomainObjPtr privdom = NULL;
2103
    virDomainDefPtr persistentDef;
C
Cole Robinson 已提交
2104 2105
    int ret = -1, maxvcpus;

2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121
    virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
                  VIR_DOMAIN_VCPU_CONFIG |
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

    /* At least one of LIVE or CONFIG must be set.  MAXIMUM cannot be
     * mixed with LIVE.  */
    if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0 ||
        (flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) ==
         (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) {
        testError(VIR_ERR_INVALID_ARG,
                  _("invalid flag combination: (0x%x)"), flags);
        return -1;
    }
    if (!nrCpus || (maxvcpus = testGetMaxVCPUs(domain->conn, NULL)) < nrCpus) {
        testError(VIR_ERR_INVALID_ARG,
                  _("argument out of range: %d"), nrCpus);
2122 2123
        return -1;
    }
2124

2125
    testDriverLock(privconn);
2126
    privdom = virDomainFindByUUID(&privconn->domains, domain->uuid);
2127 2128 2129
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2130
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2131
        goto cleanup;
2132
    }
2133

2134
    if (!virDomainObjIsActive(privdom) && (flags & VIR_DOMAIN_VCPU_LIVE)) {
2135
        testError(VIR_ERR_OPERATION_INVALID,
C
Cole Robinson 已提交
2136 2137 2138 2139
                  "%s", _("cannot hotplug vcpus for an inactive domain"));
        goto cleanup;
    }

2140 2141
    /* We allow more cpus in guest than host, but not more than the
     * domain's starting limit.  */
C
Cole Robinson 已提交
2142 2143
    if (!(flags & (VIR_DOMAIN_VCPU_MAXIMUM)) &&
        privdom->def->maxvcpus < maxvcpus)
2144
        maxvcpus = privdom->def->maxvcpus;
C
Cole Robinson 已提交
2145

C
Cole Robinson 已提交
2146
    if (nrCpus > maxvcpus) {
2147
        testError(VIR_ERR_INVALID_ARG,
C
Cole Robinson 已提交
2148 2149
                  "requested cpu amount exceeds maximum (%d > %d)",
                  nrCpus, maxvcpus);
2150
        goto cleanup;
2151
    }
2152

2153 2154 2155 2156
    if (!(persistentDef = virDomainObjGetPersistentDef(privconn->caps,
                                                       privdom)))
        goto cleanup;

2157 2158
    switch (flags) {
    case VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_CONFIG:
2159 2160 2161
        persistentDef->maxvcpus = nrCpus;
        if (nrCpus < persistentDef->vcpus)
            persistentDef->vcpus = nrCpus;
2162 2163
        ret = 0;
        break;
2164

2165
    case VIR_DOMAIN_VCPU_CONFIG:
2166
        persistentDef->vcpus = nrCpus;
2167 2168 2169 2170 2171 2172 2173 2174 2175
        ret = 0;
        break;

    case VIR_DOMAIN_VCPU_LIVE:
        ret = testDomainUpdateVCPUs(domain->conn, privdom, nrCpus, 0);
        break;

    case VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG:
        ret = testDomainUpdateVCPUs(domain->conn, privdom, nrCpus, 0);
2176 2177 2178
        if (ret == 0) {
            persistentDef->vcpus = nrCpus;
        }
2179 2180
        break;
    }
2181 2182

cleanup:
2183 2184
    if (privdom)
        virDomainObjUnlock(privdom);
2185
    return ret;
2186 2187
}

2188 2189 2190 2191 2192 2193
static int
testSetVcpus(virDomainPtr domain, unsigned int nrCpus)
{
    return testDomainSetVcpusFlags(domain, nrCpus, VIR_DOMAIN_VCPU_LIVE);
}

C
Cole Robinson 已提交
2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212
static int testDomainGetVcpus(virDomainPtr domain,
                              virVcpuInfoPtr info,
                              int maxinfo,
                              unsigned char *cpumaps,
                              int maplen)
{
    testConnPtr privconn = domain->conn->privateData;
    testDomainObjPrivatePtr privdomdata;
    virDomainObjPtr privdom;
    int i, v, maxcpu, hostcpus;
    int ret = -1;
    struct timeval tv;
    unsigned long long statbase;

    testDriverLock(privconn);
    privdom = virDomainFindByName(&privconn->domains, domain->name);
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2213
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
C
Cole Robinson 已提交
2214 2215 2216 2217
        goto cleanup;
    }

    if (!virDomainObjIsActive(privdom)) {
2218
        testError(VIR_ERR_OPERATION_INVALID,
C
Cole Robinson 已提交
2219 2220 2221 2222 2223 2224 2225
                  "%s",_("cannot list vcpus for an inactive domain"));
        goto cleanup;
    }

    privdomdata = privdom->privateData;

    if (gettimeofday(&tv, NULL) < 0) {
2226
        virReportSystemError(errno,
C
Cole Robinson 已提交
2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281
                             "%s", _("getting time of day"));
        goto cleanup;
    }

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


    hostcpus = VIR_NODEINFO_MAXCPUS(privconn->nodeInfo);
    maxcpu = maplen * 8;
    if (maxcpu > hostcpus)
        maxcpu = hostcpus;

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

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

        for (i = 0 ; i < maxinfo ; i++) {
            virVcpuInfo privinfo = privdomdata->vcpu_infos[i];

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

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

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

        for (v = 0 ; v < maxinfo ; v++) {
            unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v);

            for (i = 0 ; i < maxcpu ; i++) {
                if (VIR_CPU_USABLE(privdomdata->cpumaps, privmaplen, v, i)) {
                    VIR_USE_CPU(cpumap, i);
                }
            }
        }
    }

    ret = maxinfo;
cleanup:
    if (privdom)
        virDomainObjUnlock(privdom);
    return ret;
}

C
Cole Robinson 已提交
2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298
static int testDomainPinVcpu(virDomainPtr domain,
                             unsigned int vcpu,
                             unsigned char *cpumap,
                             int maplen)
{
    testConnPtr privconn = domain->conn->privateData;
    testDomainObjPrivatePtr privdomdata;
    virDomainObjPtr privdom;
    unsigned char *privcpumap;
    int i, maxcpu, hostcpus, privmaplen;
    int ret = -1;

    testDriverLock(privconn);
    privdom = virDomainFindByName(&privconn->domains, domain->name);
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2299
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
C
Cole Robinson 已提交
2300 2301 2302 2303
        goto cleanup;
    }

    if (!virDomainObjIsActive(privdom)) {
2304
        testError(VIR_ERR_OPERATION_INVALID,
C
Cole Robinson 已提交
2305 2306 2307 2308 2309
                  "%s",_("cannot pin vcpus on an inactive domain"));
        goto cleanup;
    }

    if (vcpu > privdom->def->vcpus) {
2310
        testError(VIR_ERR_INVALID_ARG, "%s",
C
Cole Robinson 已提交
2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338
                  _("requested vcpu is higher than allocated vcpus"));
        goto cleanup;
    }

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

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

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

    for (i = 0 ; i < maxcpu ; i++) {
        if (VIR_CPU_USABLE(cpumap, maplen, 0, i)) {
            VIR_USE_CPU(privcpumap, i);
        }
    }

    ret = 0;
cleanup:
    if (privdom)
        virDomainObjUnlock(privdom);
    return ret;
}

2339
static char *testDomainDumpXML(virDomainPtr domain, int flags)
2340
{
2341
    testConnPtr privconn = domain->conn->privateData;
2342
    virDomainDefPtr def;
2343
    virDomainObjPtr privdom;
2344 2345
    char *ret = NULL;

2346 2347 2348 2349 2350 2351
    testDriverLock(privconn);
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2352
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2353
        goto cleanup;
2354
    }
2355

2356 2357
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
2358

2359
    ret = virDomainDefFormat(def,
2360 2361 2362
                             flags);

cleanup:
2363 2364
    if (privdom)
        virDomainObjUnlock(privdom);
2365
    return ret;
2366
}
2367

2368
static int testNumOfDefinedDomains(virConnectPtr conn) {
2369
    testConnPtr privconn = conn->privateData;
2370
    int count;
2371

2372
    testDriverLock(privconn);
2373
    count = virDomainObjListNumOfDomains(&privconn->domains, 0);
2374
    testDriverUnlock(privconn);
2375

2376
    return count;
2377 2378
}

2379 2380 2381
static int testListDefinedDomains(virConnectPtr conn,
                                  char **const names,
                                  int maxnames) {
2382

2383
    testConnPtr privconn = conn->privateData;
2384
    int n;
2385

2386
    testDriverLock(privconn);
2387
    memset(names, 0, sizeof(*names)*maxnames);
2388
    n = virDomainObjListGetInactiveNames(&privconn->domains, names, maxnames);
2389
    testDriverUnlock(privconn);
2390

2391
    return n;
2392 2393
}

2394
static virDomainPtr testDomainDefineXML(virConnectPtr conn,
2395
                                        const char *xml) {
2396
    testConnPtr privconn = conn->privateData;
2397
    virDomainPtr ret = NULL;
2398
    virDomainDefPtr def;
2399
    virDomainObjPtr dom = NULL;
2400
    virDomainEventPtr event = NULL;
2401
    int dupVM;
2402

2403
    testDriverLock(privconn);
2404
    if ((def = virDomainDefParseString(privconn->caps, xml,
2405
                                       VIR_DOMAIN_XML_INACTIVE)) == NULL)
2406
        goto cleanup;
2407

2408 2409 2410
    if ((dupVM = virDomainObjIsDuplicate(&privconn->domains, def, 0)) < 0)
        goto cleanup;

2411
    if (testDomainGenerateIfnames(def) < 0)
2412
        goto cleanup;
2413
    if (!(dom = virDomainAssignDef(privconn->caps,
2414
                                   &privconn->domains, def, false)))
2415
        goto cleanup;
2416
    def = NULL;
2417
    dom->persistent = 1;
2418

2419 2420
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_DEFINED,
2421 2422 2423
                                     !dupVM ?
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
2424

2425
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
2426
    if (ret)
2427
        ret->id = dom->def->id;
2428 2429 2430

cleanup:
    virDomainDefFree(def);
2431 2432
    if (dom)
        virDomainObjUnlock(dom);
2433 2434
    if (event)
        testDomainEventQueue(privconn, event);
2435
    testDriverUnlock(privconn);
2436
    return ret;
2437 2438
}

2439 2440 2441
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
                                      int startCell, int maxCells) {
2442
    testConnPtr privconn = conn->privateData;
2443
    int i, j;
2444
    int ret = -1;
2445

2446
    testDriverLock(privconn);
2447
    if (startCell > privconn->numCells) {
2448
        testError(VIR_ERR_INVALID_ARG,
J
Jim Meyering 已提交
2449
                  "%s", _("Range exceeds available cells"));
2450
        goto cleanup;
2451 2452 2453 2454 2455 2456 2457
    }

    for (i = startCell, j = 0;
         (i < privconn->numCells && j < maxCells) ;
         ++i, ++j) {
        freemems[j] = privconn->cells[i].mem;
    }
2458
    ret = j;
2459

2460
cleanup:
2461
    testDriverUnlock(privconn);
2462
    return ret;
2463 2464 2465
}


2466
static int testDomainCreateWithFlags(virDomainPtr domain, unsigned int flags) {
2467 2468
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2469
    virDomainEventPtr event = NULL;
2470
    int ret = -1;
2471

2472 2473
    virCheckFlags(0, -1);

2474
    testDriverLock(privconn);
2475 2476 2477 2478
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
2479
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2480
        goto cleanup;
2481
    }
2482

2483
    if (privdom->state != VIR_DOMAIN_SHUTOFF) {
2484
        testError(VIR_ERR_INTERNAL_ERROR,
2485
                  _("Domain '%s' is already running"), domain->name);
2486
        goto cleanup;
2487 2488
    }

2489 2490 2491 2492
    if (testDomainStartState(domain->conn, privdom) < 0)
        goto cleanup;
    domain->id = privdom->def->id;

2493 2494 2495
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
2496
    ret = 0;
2497

2498
cleanup:
2499 2500
    if (privdom)
        virDomainObjUnlock(privdom);
2501 2502
    if (event)
        testDomainEventQueue(privconn, event);
2503
    testDriverUnlock(privconn);
2504
    return ret;
2505 2506
}

2507 2508 2509 2510
static int testDomainCreate(virDomainPtr domain) {
    return testDomainCreateWithFlags(domain, 0);
}

2511
static int testDomainUndefine(virDomainPtr domain) {
2512 2513
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2514
    virDomainEventPtr event = NULL;
2515
    int ret = -1;
2516

2517
    testDriverLock(privconn);
2518 2519 2520 2521
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);

    if (privdom == NULL) {
2522
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2523
        goto cleanup;
2524
    }
2525

2526
    if (privdom->state != VIR_DOMAIN_SHUTOFF) {
2527
        testError(VIR_ERR_INTERNAL_ERROR,
2528
                  _("Domain '%s' is still running"), domain->name);
2529
        goto cleanup;
2530 2531
    }

2532
    privdom->state = VIR_DOMAIN_SHUTOFF;
2533 2534 2535
    event = virDomainEventNewFromObj(privdom,
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
2536 2537
    virDomainRemoveInactive(&privconn->domains,
                            privdom);
2538
    privdom = NULL;
2539
    ret = 0;
2540

2541
cleanup:
2542 2543
    if (privdom)
        virDomainObjUnlock(privdom);
2544 2545
    if (event)
        testDomainEventQueue(privconn, event);
2546
    testDriverUnlock(privconn);
2547
    return ret;
2548 2549
}

2550 2551 2552
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
2553 2554
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2555
    int ret = -1;
2556

2557
    testDriverLock(privconn);
2558 2559
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
2560
    testDriverUnlock(privconn);
2561 2562

    if (privdom == NULL) {
2563
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2564
        goto cleanup;
2565 2566
    }

2567
    *autostart = privdom->autostart;
2568 2569 2570
    ret = 0;

cleanup:
2571 2572
    if (privdom)
        virDomainObjUnlock(privdom);
2573
    return ret;
2574 2575 2576 2577 2578 2579
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
2580 2581
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2582
    int ret = -1;
2583

2584
    testDriverLock(privconn);
2585 2586
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
2587
    testDriverUnlock(privconn);
2588 2589

    if (privdom == NULL) {
2590
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2591
        goto cleanup;
2592 2593
    }

2594
    privdom->autostart = autostart ? 1 : 0;
2595 2596 2597
    ret = 0;

cleanup:
2598 2599
    if (privdom)
        virDomainObjUnlock(privdom);
2600
    return ret;
2601
}
2602

2603
static char *testDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED,
2604 2605
                                        int *nparams)
{
2606 2607
    char *type = NULL;

2608 2609
    *nparams = 1;
    type = strdup("fair");
2610
    if (!type)
2611
        virReportOOMError();
2612

2613 2614 2615 2616 2617 2618 2619
    return type;
}

static int testDomainGetSchedulerParams(virDomainPtr domain,
                                        virSchedParameterPtr params,
                                        int *nparams)
{
2620 2621
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2622
    int ret = -1;
2623

2624
    testDriverLock(privconn);
2625 2626
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
2627
    testDriverUnlock(privconn);
2628 2629

    if (privdom == NULL) {
2630
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2631
        goto cleanup;
2632 2633
    }

2634
    if (*nparams != 1) {
2635
        testError(VIR_ERR_INVALID_ARG, "nparams");
2636
        goto cleanup;
2637
    }
2638 2639
    strcpy(params[0].field, "weight");
    params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT;
2640 2641 2642
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
    params[0].value.ui = 50;
2643 2644 2645
    ret = 0;

cleanup:
2646 2647
    if (privdom)
        virDomainObjUnlock(privdom);
2648
    return ret;
2649
}
2650 2651


2652 2653 2654 2655
static int testDomainSetSchedulerParams(virDomainPtr domain,
                                        virSchedParameterPtr params,
                                        int nparams)
{
2656 2657
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
2658
    int ret = -1;
2659

2660
    testDriverLock(privconn);
2661 2662
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
2663
    testDriverUnlock(privconn);
2664 2665

    if (privdom == NULL) {
2666
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2667
        goto cleanup;
2668 2669
    }

2670
    if (nparams != 1) {
2671
        testError(VIR_ERR_INVALID_ARG, "nparams");
2672
        goto cleanup;
2673
    }
2674
    if (STRNEQ(params[0].field, "weight")) {
2675
        testError(VIR_ERR_INVALID_ARG, "field");
2676
        goto cleanup;
2677 2678
    }
    if (params[0].type != VIR_DOMAIN_SCHED_FIELD_UINT) {
2679
        testError(VIR_ERR_INVALID_ARG, "type");
2680
        goto cleanup;
2681
    }
2682 2683
    /* XXX */
    /*privdom->weight = params[0].value.ui;*/
2684 2685 2686
    ret = 0;

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

2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707
static int testDomainBlockStats(virDomainPtr domain,
                                const char *path,
                                struct _virDomainBlockStats *stats)
{
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
    int i, found = 0, ret = -1;

    testDriverLock(privconn);
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2708
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719
        goto error;
    }

    for (i = 0 ; i < privdom->def->ndisks ; i++) {
        if (STREQ(path, privdom->def->disks[i]->dst)) {
            found = 1;
            break;
        }
    }

    if (!found) {
2720
        testError(VIR_ERR_INVALID_ARG,
2721 2722 2723 2724 2725
                  _("invalid path: %s"), path);
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
2726
        virReportSystemError(errno,
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 2757 2758 2759 2760 2761
                             "%s", _("getting time of day"));
        goto error;
    }

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

    ret = 0;
error:
    if (privdom)
        virDomainObjUnlock(privdom);
    return ret;
}

static int testDomainInterfaceStats(virDomainPtr domain,
                                    const char *path,
                                    struct _virDomainInterfaceStats *stats)
{
    testConnPtr privconn = domain->conn->privateData;
    virDomainObjPtr privdom;
    struct timeval tv;
    unsigned long long statbase;
    int i, found = 0, ret = -1;

    testDriverLock(privconn);
    privdom = virDomainFindByName(&privconn->domains,
                                  domain->name);
    testDriverUnlock(privconn);

    if (privdom == NULL) {
2762
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774
        goto error;
    }

    for (i = 0 ; i < privdom->def->nnets ; i++) {
        if (privdom->def->nets[i]->ifname &&
            STREQ (privdom->def->nets[i]->ifname, path)) {
            found = 1;
            break;
        }
    }

    if (!found) {
2775
        testError(VIR_ERR_INVALID_ARG,
2776 2777 2778 2779 2780
                  _("invalid path, '%s' is not a known interface"), path);
        goto error;
    }

    if (gettimeofday(&tv, NULL) < 0) {
2781
        virReportSystemError(errno,
2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803
                             "%s", _("getting time of day"));
        goto error;
    }

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

    ret = 0;
error:
    if (privdom)
        virDomainObjUnlock(privdom);
    return ret;
}

2804
static virDrvOpenStatus testOpenNetwork(virConnectPtr conn,
2805
                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822
                                        int flags ATTRIBUTE_UNUSED) {
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

    conn->networkPrivateData = conn->privateData;
    return VIR_DRV_OPEN_SUCCESS;
}

static int testCloseNetwork(virConnectPtr conn) {
    conn->networkPrivateData = NULL;
    return 0;
}


static virNetworkPtr testLookupNetworkByUUID(virConnectPtr conn,
                                           const unsigned char *uuid)
{
2823 2824
    testConnPtr privconn = conn->privateData;
    virNetworkObjPtr net;
2825
    virNetworkPtr ret = NULL;
2826

2827 2828 2829 2830 2831
    testDriverLock(privconn);
    net = virNetworkFindByUUID(&privconn->networks, uuid);
    testDriverUnlock(privconn);

    if (net == NULL) {
2832
        testError(VIR_ERR_NO_NETWORK, NULL);
2833
        goto cleanup;
2834 2835
    }

2836 2837 2838
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

cleanup:
2839 2840
    if (net)
        virNetworkObjUnlock(net);
2841
    return ret;
2842
}
2843

2844
static virNetworkPtr testLookupNetworkByName(virConnectPtr conn,
2845
                                             const char *name)
2846
{
2847
    testConnPtr privconn = conn->privateData;
2848 2849
    virNetworkObjPtr net;
    virNetworkPtr ret = NULL;
2850

2851 2852 2853 2854 2855
    testDriverLock(privconn);
    net = virNetworkFindByName(&privconn->networks, name);
    testDriverUnlock(privconn);

    if (net == NULL) {
2856
        testError(VIR_ERR_NO_NETWORK, NULL);
2857
        goto cleanup;
2858 2859
    }

2860 2861 2862
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);

cleanup:
2863 2864
    if (net)
        virNetworkObjUnlock(net);
2865
    return ret;
2866 2867 2868 2869
}


static int testNumNetworks(virConnectPtr conn) {
2870
    testConnPtr privconn = conn->privateData;
2871
    int numActive = 0, i;
2872

2873 2874 2875
    testDriverLock(privconn);
    for (i = 0 ; i < privconn->networks.count ; i++) {
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
2876
        if (virNetworkObjIsActive(privconn->networks.objs[i]))
2877
            numActive++;
2878 2879 2880
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
2881

2882
    return numActive;
2883 2884 2885
}

static int testListNetworks(virConnectPtr conn, char **const names, int nnames) {
2886
    testConnPtr privconn = conn->privateData;
2887
    int n = 0, i;
2888

2889
    testDriverLock(privconn);
2890
    memset(names, 0, sizeof(*names)*nnames);
2891 2892
    for (i = 0 ; i < privconn->networks.count && n < nnames ; i++) {
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
2893
        if (virNetworkObjIsActive(privconn->networks.objs[i]) &&
2894 2895
            !(names[n++] = strdup(privconn->networks.objs[i]->def->name))) {
            virNetworkObjUnlock(privconn->networks.objs[i]);
2896
            goto no_memory;
2897 2898 2899 2900
        }
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
2901

2902 2903 2904
    return n;

no_memory:
2905
    virReportOOMError();
2906 2907
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
2908
    testDriverUnlock(privconn);
2909
    return -1;
2910 2911 2912
}

static int testNumDefinedNetworks(virConnectPtr conn) {
2913
    testConnPtr privconn = conn->privateData;
2914
    int numInactive = 0, i;
2915

2916 2917 2918
    testDriverLock(privconn);
    for (i = 0 ; i < privconn->networks.count ; i++) {
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
2919
        if (!virNetworkObjIsActive(privconn->networks.objs[i]))
2920
            numInactive++;
2921 2922 2923
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
2924

2925
    return numInactive;
2926 2927 2928
}

static int testListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
2929
    testConnPtr privconn = conn->privateData;
2930
    int n = 0, i;
2931

2932
    testDriverLock(privconn);
2933
    memset(names, 0, sizeof(*names)*nnames);
2934 2935
    for (i = 0 ; i < privconn->networks.count && n < nnames ; i++) {
        virNetworkObjLock(privconn->networks.objs[i]);
D
Daniel P. Berrange 已提交
2936
        if (!virNetworkObjIsActive(privconn->networks.objs[i]) &&
2937 2938
            !(names[n++] = strdup(privconn->networks.objs[i]->def->name))) {
            virNetworkObjUnlock(privconn->networks.objs[i]);
2939
            goto no_memory;
2940 2941 2942 2943
        }
        virNetworkObjUnlock(privconn->networks.objs[i]);
    }
    testDriverUnlock(privconn);
2944

2945 2946 2947
    return n;

no_memory:
2948
    virReportOOMError();
2949 2950
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
2951
    testDriverUnlock(privconn);
2952
    return -1;
2953 2954
}

2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965

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

    testDriverLock(privconn);
    obj = virNetworkFindByUUID(&privconn->networks, net->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
2966
        testError(VIR_ERR_NO_NETWORK, NULL);
2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986
        goto cleanup;
    }
    ret = virNetworkObjIsActive(obj);

cleanup:
    if (obj)
        virNetworkObjUnlock(obj);
    return ret;
}

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

    testDriverLock(privconn);
    obj = virNetworkFindByUUID(&privconn->networks, net->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
2987
        testError(VIR_ERR_NO_NETWORK, NULL);
2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998
        goto cleanup;
    }
    ret = obj->persistent;

cleanup:
    if (obj)
        virNetworkObjUnlock(obj);
    return ret;
}


2999
static virNetworkPtr testNetworkCreate(virConnectPtr conn, const char *xml) {
3000
    testConnPtr privconn = conn->privateData;
3001
    virNetworkDefPtr def;
3002
    virNetworkObjPtr net = NULL;
3003
    virNetworkPtr ret = NULL;
3004

3005
    testDriverLock(privconn);
3006
    if ((def = virNetworkDefParseString(xml)) == NULL)
3007
        goto cleanup;
3008

3009
    if ((net = virNetworkAssignDef(&privconn->networks, def)) == NULL)
3010 3011
        goto cleanup;
    def = NULL;
3012
    net->active = 1;
3013

3014
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3015

3016 3017
cleanup:
    virNetworkDefFree(def);
3018 3019 3020
    if (net)
        virNetworkObjUnlock(net);
    testDriverUnlock(privconn);
3021
    return ret;
3022 3023 3024
}

static virNetworkPtr testNetworkDefine(virConnectPtr conn, const char *xml) {
3025
    testConnPtr privconn = conn->privateData;
3026
    virNetworkDefPtr def;
3027
    virNetworkObjPtr net = NULL;
3028
    virNetworkPtr ret = NULL;
3029

3030
    testDriverLock(privconn);
3031
    if ((def = virNetworkDefParseString(xml)) == NULL)
3032
        goto cleanup;
3033

3034
    if ((net = virNetworkAssignDef(&privconn->networks, def)) == NULL)
3035 3036
        goto cleanup;
    def = NULL;
3037
    net->persistent = 1;
3038

3039
    ret = virGetNetwork(conn, net->def->name, net->def->uuid);
3040 3041 3042

cleanup:
    virNetworkDefFree(def);
3043 3044 3045
    if (net)
        virNetworkObjUnlock(net);
    testDriverUnlock(privconn);
3046
    return ret;
3047 3048 3049
}

static int testNetworkUndefine(virNetworkPtr network) {
3050 3051
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3052
    int ret = -1;
3053

3054
    testDriverLock(privconn);
3055 3056 3057 3058
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
3059
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3060
        goto cleanup;
3061
    }
3062

D
Daniel P. Berrange 已提交
3063
    if (virNetworkObjIsActive(privnet)) {
3064
        testError(VIR_ERR_OPERATION_INVALID,
3065
                  _("Network '%s' is still running"), network->name);
3066
        goto cleanup;
3067 3068
    }

3069 3070
    virNetworkRemoveInactive(&privconn->networks,
                             privnet);
3071
    privnet = NULL;
3072
    ret = 0;
3073

3074
cleanup:
3075 3076 3077
    if (privnet)
        virNetworkObjUnlock(privnet);
    testDriverUnlock(privconn);
3078
    return ret;
3079 3080 3081
}

static int testNetworkStart(virNetworkPtr network) {
3082 3083
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3084
    int ret = -1;
3085

3086
    testDriverLock(privconn);
3087 3088
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
3089
    testDriverUnlock(privconn);
3090 3091

    if (privnet == NULL) {
3092
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3093
        goto cleanup;
3094
    }
3095

D
Daniel P. Berrange 已提交
3096
    if (virNetworkObjIsActive(privnet)) {
3097
        testError(VIR_ERR_OPERATION_INVALID,
3098
                  _("Network '%s' is already running"), network->name);
3099
        goto cleanup;
3100 3101
    }

3102
    privnet->active = 1;
3103
    ret = 0;
3104

3105
cleanup:
3106 3107
    if (privnet)
        virNetworkObjUnlock(privnet);
3108
    return ret;
3109 3110 3111
}

static int testNetworkDestroy(virNetworkPtr network) {
3112 3113
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3114
    int ret = -1;
3115

3116
    testDriverLock(privconn);
3117 3118 3119 3120
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);

    if (privnet == NULL) {
3121
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3122
        goto cleanup;
3123
    }
3124

3125 3126 3127 3128
    privnet->active = 0;
    if (!privnet->persistent) {
        virNetworkRemoveInactive(&privconn->networks,
                                 privnet);
3129
        privnet = NULL;
3130
    }
3131 3132 3133
    ret = 0;

cleanup:
3134 3135 3136
    if (privnet)
        virNetworkObjUnlock(privnet);
    testDriverUnlock(privconn);
3137
    return ret;
3138 3139 3140
}

static char *testNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) {
3141 3142
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3143
    char *ret = NULL;
3144

3145
    testDriverLock(privconn);
3146 3147
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
3148
    testDriverUnlock(privconn);
3149 3150

    if (privnet == NULL) {
3151
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3152
        goto cleanup;
3153
    }
3154

3155
    ret = virNetworkDefFormat(privnet->def);
3156 3157

cleanup:
3158 3159
    if (privnet)
        virNetworkObjUnlock(privnet);
3160
    return ret;
3161 3162 3163
}

static char *testNetworkGetBridgeName(virNetworkPtr network) {
3164
    testConnPtr privconn = network->conn->privateData;
3165
    char *bridge = NULL;
3166 3167
    virNetworkObjPtr privnet;

3168
    testDriverLock(privconn);
3169 3170
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
3171
    testDriverUnlock(privconn);
3172 3173

    if (privnet == NULL) {
3174
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3175
        goto cleanup;
3176 3177
    }

3178
    if (!(privnet->def->bridge)) {
3179
        testError(VIR_ERR_INTERNAL_ERROR,
3180 3181 3182 3183 3184 3185
                  _("network '%s' does not have a bridge name."),
                  privnet->def->name);
        goto cleanup;
    }

    if (!(bridge = strdup(privnet->def->bridge))) {
3186
        virReportOOMError();
3187
        goto cleanup;
3188
    }
3189 3190

cleanup:
3191 3192
    if (privnet)
        virNetworkObjUnlock(privnet);
3193 3194 3195 3196 3197
    return bridge;
}

static int testNetworkGetAutostart(virNetworkPtr network,
                                   int *autostart) {
3198 3199
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3200
    int ret = -1;
3201

3202
    testDriverLock(privconn);
3203 3204
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
3205
    testDriverUnlock(privconn);
3206 3207

    if (privnet == NULL) {
3208
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3209
        goto cleanup;
3210 3211
    }

3212
    *autostart = privnet->autostart;
3213 3214 3215
    ret = 0;

cleanup:
3216 3217
    if (privnet)
        virNetworkObjUnlock(privnet);
3218
    return ret;
3219 3220 3221 3222
}

static int testNetworkSetAutostart(virNetworkPtr network,
                                   int autostart) {
3223 3224
    testConnPtr privconn = network->conn->privateData;
    virNetworkObjPtr privnet;
3225
    int ret = -1;
3226

3227
    testDriverLock(privconn);
3228 3229
    privnet = virNetworkFindByName(&privconn->networks,
                                   network->name);
3230
    testDriverUnlock(privconn);
3231 3232

    if (privnet == NULL) {
3233
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3234
        goto cleanup;
3235 3236
    }

3237
    privnet->autostart = autostart ? 1 : 0;
3238 3239 3240
    ret = 0;

cleanup:
3241 3242
    if (privnet)
        virNetworkObjUnlock(privnet);
3243
    return ret;
3244
}
3245

C
Cole Robinson 已提交
3246

L
Laine Stump 已提交
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
/*
 * Physical host interface routines
 */

static virDrvOpenStatus testOpenInterface(virConnectPtr conn,
                                          virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                          int flags ATTRIBUTE_UNUSED)
{
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

    conn->interfacePrivateData = conn->privateData;
    return VIR_DRV_OPEN_SUCCESS;
}

static int testCloseInterface(virConnectPtr conn)
{
    conn->interfacePrivateData = NULL;
    return 0;
}


static int testNumOfInterfaces(virConnectPtr conn)
{
    testConnPtr privconn = conn->privateData;
    int i, count = 0;

    testDriverLock(privconn);
    for (i = 0 ; (i < privconn->ifaces.count); i++) {
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3277
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
L
Laine Stump 已提交
3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294
            count++;
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

static int testListInterfaces(virConnectPtr conn, char **const names, int nnames)
{
    testConnPtr privconn = conn->privateData;
    int n = 0, i;

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
    for (i = 0 ; (i < privconn->ifaces.count) && (n < nnames); i++) {
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3295
        if (virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
L
Laine Stump 已提交
3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307
            if (!(names[n++] = strdup(privconn->ifaces.objs[i]->def->name))) {
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
                goto no_memory;
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

no_memory:
3308
    virReportOOMError();
L
Laine Stump 已提交
3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

static int testNumOfDefinedInterfaces(virConnectPtr conn)
{
    testConnPtr privconn = conn->privateData;
    int i, count = 0;

    testDriverLock(privconn);
    for (i = 0 ; i < privconn->ifaces.count; i++) {
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3323
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
L
Laine Stump 已提交
3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340
            count++;
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);
    return count;
}

static int testListDefinedInterfaces(virConnectPtr conn, char **const names, int nnames)
{
    testConnPtr privconn = conn->privateData;
    int n = 0, i;

    testDriverLock(privconn);
    memset(names, 0, sizeof(*names)*nnames);
    for (i = 0 ; (i < privconn->ifaces.count) && (n < nnames); i++) {
        virInterfaceObjLock(privconn->ifaces.objs[i]);
D
Daniel P. Berrange 已提交
3341
        if (!virInterfaceObjIsActive(privconn->ifaces.objs[i])) {
L
Laine Stump 已提交
3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353
            if (!(names[n++] = strdup(privconn->ifaces.objs[i]->def->name))) {
                virInterfaceObjUnlock(privconn->ifaces.objs[i]);
                goto no_memory;
            }
        }
        virInterfaceObjUnlock(privconn->ifaces.objs[i]);
    }
    testDriverUnlock(privconn);

    return n;

no_memory:
3354
    virReportOOMError();
L
Laine Stump 已提交
3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
    testDriverUnlock(privconn);
    return -1;
}

static virInterfacePtr testLookupInterfaceByName(virConnectPtr conn,
                                                 const char *name)
{
    testConnPtr privconn = conn->privateData;
    virInterfaceObjPtr iface;
    virInterfacePtr ret = NULL;

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

    if (iface == NULL) {
3373
        testError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397
        goto cleanup;
    }

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

cleanup:
    if (iface)
        virInterfaceObjUnlock(iface);
    return ret;
}

static virInterfacePtr testLookupInterfaceByMACString(virConnectPtr conn,
                                                      const char *mac)
{
    testConnPtr privconn = conn->privateData;
    virInterfaceObjPtr iface;
    int ifacect;
    virInterfacePtr ret = NULL;

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

    if (ifacect == 0) {
3398
        testError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3399 3400 3401 3402
        goto cleanup;
    }

    if (ifacect > 1) {
3403
        testError(VIR_ERR_MULTIPLE_INTERFACES, NULL);
L
Laine Stump 已提交
3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414
        goto cleanup;
    }

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

cleanup:
    if (iface)
        virInterfaceObjUnlock(iface);
    return ret;
}

3415 3416 3417 3418 3419 3420 3421 3422 3423 3424
static int testInterfaceIsActive(virInterfacePtr iface)
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virInterfaceFindByName(&privconn->ifaces, iface->name);
    testDriverUnlock(privconn);
    if (!obj) {
3425
        testError(VIR_ERR_NO_INTERFACE, NULL);
3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436
        goto cleanup;
    }
    ret = virInterfaceObjIsActive(obj);

cleanup:
    if (obj)
        virInterfaceObjUnlock(obj);
    return ret;
}


L
Laine Stump 已提交
3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449
static char *testInterfaceGetXMLDesc(virInterfacePtr iface,
                                     unsigned int flags ATTRIBUTE_UNUSED)
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr privinterface;
    char *ret = NULL;

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

    if (privinterface == NULL) {
3450
        testError(VIR_ERR_NO_INTERFACE, __FUNCTION__);
L
Laine Stump 已提交
3451 3452 3453
        goto cleanup;
    }

3454
    ret = virInterfaceDefFormat(privinterface->def);
L
Laine Stump 已提交
3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471

cleanup:
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    return ret;
}


static virInterfacePtr testInterfaceDefineXML(virConnectPtr conn, const char *xmlStr,
                                              unsigned int flags ATTRIBUTE_UNUSED)
{
    testConnPtr privconn = conn->privateData;
    virInterfaceDefPtr def;
    virInterfaceObjPtr iface = NULL;
    virInterfacePtr ret = NULL;

    testDriverLock(privconn);
3472
    if ((def = virInterfaceDefParseString(xmlStr)) == NULL)
L
Laine Stump 已提交
3473 3474
        goto cleanup;

3475
    if ((iface = virInterfaceAssignDef(&privconn->ifaces, def)) == NULL)
L
Laine Stump 已提交
3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499
        goto cleanup;
    def = NULL;

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

cleanup:
    virInterfaceDefFree(def);
    if (iface)
        virInterfaceObjUnlock(iface);
    testDriverUnlock(privconn);
    return ret;
}

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

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

    if (privinterface == NULL) {
3500
        testError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524
        goto cleanup;
    }

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

cleanup:
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceCreate(virInterfacePtr iface,
                               unsigned int flags ATTRIBUTE_UNUSED)
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr privinterface;
    int ret = -1;

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

    if (privinterface == NULL) {
3525
        testError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3526 3527 3528 3529
        goto cleanup;
    }

    if (privinterface->active != 0) {
3530
        testError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555
        goto cleanup;
    }

    privinterface->active = 1;
    ret = 0;

cleanup:
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    testDriverUnlock(privconn);
    return ret;
}

static int testInterfaceDestroy(virInterfacePtr iface,
                                unsigned int flags ATTRIBUTE_UNUSED)
{
    testConnPtr privconn = iface->conn->privateData;
    virInterfaceObjPtr privinterface;
    int ret = -1;

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

    if (privinterface == NULL) {
3556
        testError(VIR_ERR_NO_INTERFACE, NULL);
L
Laine Stump 已提交
3557 3558 3559 3560
        goto cleanup;
    }

    if (privinterface->active == 0) {
3561
        testError(VIR_ERR_OPERATION_INVALID, NULL);
L
Laine Stump 已提交
3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576
        goto cleanup;
    }

    privinterface->active = 0;
    ret = 0;

cleanup:
    if (privinterface)
        virInterfaceObjUnlock(privinterface);
    testDriverUnlock(privconn);
    return ret;
}



C
Cole Robinson 已提交
3577 3578 3579 3580
/*
 * Storage Driver routines
 */

3581

3582
static int testStoragePoolObjSetDefaults(virStoragePoolObjPtr pool) {
C
Cole Robinson 已提交
3583 3584 3585 3586 3587 3588 3589

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

    pool->configFile = strdup("\0");
    if (!pool->configFile) {
3590
        virReportOOMError();
C
Cole Robinson 已提交
3591 3592 3593 3594 3595 3596
        return -1;
    }

    return 0;
}

3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611
static virDrvOpenStatus testStorageOpen(virConnectPtr conn,
                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                        int flags ATTRIBUTE_UNUSED) {
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

    conn->storagePrivateData = conn->privateData;
    return VIR_DRV_OPEN_SUCCESS;
}

static int testStorageClose(virConnectPtr conn) {
    conn->storagePrivateData = NULL;
    return 0;
}

3612

C
Cole Robinson 已提交
3613 3614 3615
static virStoragePoolPtr
testStoragePoolLookupByUUID(virConnectPtr conn,
                            const unsigned char *uuid) {
3616
    testConnPtr privconn = conn->privateData;
3617 3618
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3619

3620
    testDriverLock(privconn);
3621
    pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid);
3622
    testDriverUnlock(privconn);
3623 3624

    if (pool == NULL) {
3625
        testError(VIR_ERR_NO_STORAGE_POOL, NULL);
3626
        goto cleanup;
C
Cole Robinson 已提交
3627 3628
    }

3629 3630 3631
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
3632 3633
    if (pool)
        virStoragePoolObjUnlock(pool);
3634
    return ret;
C
Cole Robinson 已提交
3635 3636 3637 3638 3639
}

static virStoragePoolPtr
testStoragePoolLookupByName(virConnectPtr conn,
                            const char *name) {
3640
    testConnPtr privconn = conn->privateData;
3641 3642
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3643

3644
    testDriverLock(privconn);
3645
    pool = virStoragePoolObjFindByName(&privconn->pools, name);
3646
    testDriverUnlock(privconn);
3647 3648

    if (pool == NULL) {
3649
        testError(VIR_ERR_NO_STORAGE_POOL, NULL);
3650
        goto cleanup;
C
Cole Robinson 已提交
3651 3652
    }

3653 3654 3655
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
3656 3657
    if (pool)
        virStoragePoolObjUnlock(pool);
3658
    return ret;
C
Cole Robinson 已提交
3659 3660 3661 3662 3663 3664 3665 3666 3667
}

static virStoragePoolPtr
testStoragePoolLookupByVolume(virStorageVolPtr vol) {
    return testStoragePoolLookupByName(vol->conn, vol->pool);
}

static int
testStorageNumPools(virConnectPtr conn) {
3668
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
3669 3670
    int numActive = 0, i;

3671
    testDriverLock(privconn);
C
Cole Robinson 已提交
3672 3673 3674
    for (i = 0 ; i < privconn->pools.count ; i++)
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numActive++;
3675
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3676 3677 3678 3679 3680 3681 3682 3683

    return numActive;
}

static int
testStorageListPools(virConnectPtr conn,
                     char **const names,
                     int nnames) {
3684
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
3685 3686
    int n = 0, i;

3687
    testDriverLock(privconn);
C
Cole Robinson 已提交
3688
    memset(names, 0, sizeof(*names)*nnames);
3689 3690
    for (i = 0 ; i < privconn->pools.count && n < nnames ; i++) {
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3691
        if (virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
3692 3693
            !(names[n++] = strdup(privconn->pools.objs[i]->def->name))) {
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3694
            goto no_memory;
3695 3696 3697 3698
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3699 3700 3701 3702

    return n;

no_memory:
3703
    virReportOOMError();
C
Cole Robinson 已提交
3704 3705
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
3706
    testDriverUnlock(privconn);
3707
    return -1;
C
Cole Robinson 已提交
3708 3709 3710 3711
}

static int
testStorageNumDefinedPools(virConnectPtr conn) {
3712
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
3713 3714
    int numInactive = 0, i;

3715 3716 3717
    testDriverLock(privconn);
    for (i = 0 ; i < privconn->pools.count ; i++) {
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3718 3719
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]))
            numInactive++;
3720 3721 3722
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3723 3724 3725 3726 3727 3728 3729 3730

    return numInactive;
}

static int
testStorageListDefinedPools(virConnectPtr conn,
                            char **const names,
                            int nnames) {
3731
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
3732 3733
    int n = 0, i;

3734
    testDriverLock(privconn);
C
Cole Robinson 已提交
3735
    memset(names, 0, sizeof(*names)*nnames);
3736 3737
    for (i = 0 ; i < privconn->pools.count && n < nnames ; i++) {
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3738
        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
3739 3740
            !(names[n++] = strdup(privconn->pools.objs[i]->def->name))) {
            virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
3741
            goto no_memory;
3742 3743 3744 3745
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
3746 3747 3748 3749

    return n;

no_memory:
3750
    virReportOOMError();
C
Cole Robinson 已提交
3751 3752
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
3753
    testDriverUnlock(privconn);
3754
    return -1;
C
Cole Robinson 已提交
3755 3756 3757
}


3758 3759 3760 3761 3762 3763 3764 3765 3766 3767
static int testStoragePoolIsActive(virStoragePoolPtr pool)
{
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr obj;
    int ret = -1;

    testDriverLock(privconn);
    obj = virStoragePoolObjFindByUUID(&privconn->pools, pool->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
3768
        testError(VIR_ERR_NO_STORAGE_POOL, NULL);
3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788
        goto cleanup;
    }
    ret = virStoragePoolObjIsActive(obj);

cleanup:
    if (obj)
        virStoragePoolObjUnlock(obj);
    return ret;
}

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

    testDriverLock(privconn);
    obj = virStoragePoolObjFindByUUID(&privconn->pools, pool->uuid);
    testDriverUnlock(privconn);
    if (!obj) {
3789
        testError(VIR_ERR_NO_STORAGE_POOL, NULL);
3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801
        goto cleanup;
    }
    ret = obj->configFile ? 1 : 0;

cleanup:
    if (obj)
        virStoragePoolObjUnlock(obj);
    return ret;
}



C
Cole Robinson 已提交
3802
static int
3803
testStoragePoolStart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
3804
                     unsigned int flags ATTRIBUTE_UNUSED) {
3805 3806
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3807
    int ret = -1;
3808

3809
    testDriverLock(privconn);
3810 3811
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
3812
    testDriverUnlock(privconn);
3813 3814

    if (privpool == NULL) {
3815
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3816
        goto cleanup;
3817 3818
    }

3819
    if (virStoragePoolObjIsActive(privpool)) {
3820
        testError(VIR_ERR_OPERATION_INVALID,
3821 3822 3823
                  _("storage pool '%s' is already active"), pool->name);
        goto cleanup;
    }
C
Cole Robinson 已提交
3824 3825

    privpool->active = 1;
3826
    ret = 0;
C
Cole Robinson 已提交
3827

3828
cleanup:
3829 3830
    if (privpool)
        virStoragePoolObjUnlock(privpool);
3831
    return ret;
C
Cole Robinson 已提交
3832 3833 3834
}

static char *
3835
testStorageFindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
3836 3837
                           const char *type,
                           const char *srcSpec,
C
Cole Robinson 已提交
3838 3839
                           unsigned int flags ATTRIBUTE_UNUSED)
{
3840 3841 3842 3843 3844 3845
    virStoragePoolSourcePtr source = NULL;
    int pool_type;
    char *ret = NULL;

    pool_type = virStoragePoolTypeFromString(type);
    if (!pool_type) {
3846
        testError(VIR_ERR_INTERNAL_ERROR,
3847 3848 3849 3850 3851
                  _("unknown storage pool type %s"), type);
        goto cleanup;
    }

    if (srcSpec) {
3852
        source = virStoragePoolDefParseSourceString(srcSpec, pool_type);
3853 3854 3855 3856 3857 3858 3859 3860 3861
        if (!source)
            goto cleanup;
    }

    switch (pool_type) {

    case VIR_STORAGE_POOL_LOGICAL:
        ret = strdup(defaultPoolSourcesLogicalXML);
        if (!ret)
3862
            virReportOOMError();
3863 3864 3865 3866
        break;

    case VIR_STORAGE_POOL_NETFS:
        if (!source || !source->host.name) {
3867
            testError(VIR_ERR_INVALID_ARG,
3868 3869 3870 3871 3872 3873
                      "%s", "hostname must be specified for netfs sources");
            goto cleanup;
        }

        if (virAsprintf(&ret, defaultPoolSourcesNetFSXML,
                        source->host.name) < 0)
3874
            virReportOOMError();
3875 3876 3877
        break;

    default:
3878
        testError(VIR_ERR_NO_SUPPORT,
3879 3880 3881 3882 3883
                  _("pool type '%s' does not support source discovery"), type);
    }

cleanup:
    virStoragePoolSourceFree(source);
3884
    VIR_FREE(source);
3885
    return ret;
C
Cole Robinson 已提交
3886 3887 3888 3889 3890 3891 3892
}


static virStoragePoolPtr
testStoragePoolCreate(virConnectPtr conn,
                      const char *xml,
                      unsigned int flags ATTRIBUTE_UNUSED) {
3893
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
3894
    virStoragePoolDefPtr def;
3895
    virStoragePoolObjPtr pool = NULL;
3896
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3897

3898
    testDriverLock(privconn);
3899
    if (!(def = virStoragePoolDefParseString(xml)))
3900
        goto cleanup;
C
Cole Robinson 已提交
3901

3902 3903 3904 3905
    pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid);
    if (!pool)
        pool = virStoragePoolObjFindByName(&privconn->pools, def->name);
    if (pool) {
3906
        testError(VIR_ERR_INTERNAL_ERROR,
C
Cole Robinson 已提交
3907
                  "%s", _("storage pool already exists"));
3908
        goto cleanup;
C
Cole Robinson 已提交
3909 3910
    }

3911
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
3912
        goto cleanup;
3913
    def = NULL;
C
Cole Robinson 已提交
3914

3915
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
3916
        virStoragePoolObjRemove(&privconn->pools, pool);
3917 3918
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
3919 3920 3921
    }
    pool->active = 1;

3922 3923 3924 3925
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
    virStoragePoolDefFree(def);
3926 3927 3928
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
3929
    return ret;
C
Cole Robinson 已提交
3930 3931 3932 3933 3934 3935
}

static virStoragePoolPtr
testStoragePoolDefine(virConnectPtr conn,
                      const char *xml,
                      unsigned int flags ATTRIBUTE_UNUSED) {
3936
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
3937
    virStoragePoolDefPtr def;
3938
    virStoragePoolObjPtr pool = NULL;
3939
    virStoragePoolPtr ret = NULL;
C
Cole Robinson 已提交
3940

3941
    testDriverLock(privconn);
3942
    if (!(def = virStoragePoolDefParseString(xml)))
3943
        goto cleanup;
C
Cole Robinson 已提交
3944 3945 3946 3947 3948

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

3949
    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
3950 3951
        goto cleanup;
    def = NULL;
C
Cole Robinson 已提交
3952

3953
    if (testStoragePoolObjSetDefaults(pool) == -1) {
C
Cole Robinson 已提交
3954
        virStoragePoolObjRemove(&privconn->pools, pool);
3955 3956
        pool = NULL;
        goto cleanup;
C
Cole Robinson 已提交
3957 3958
    }

3959 3960 3961 3962
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

cleanup:
    virStoragePoolDefFree(def);
3963 3964 3965
    if (pool)
        virStoragePoolObjUnlock(pool);
    testDriverUnlock(privconn);
3966
    return ret;
C
Cole Robinson 已提交
3967 3968 3969
}

static int
3970 3971 3972
testStoragePoolUndefine(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
3973
    int ret = -1;
3974

3975
    testDriverLock(privconn);
3976 3977 3978 3979
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
3980
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
3981
        goto cleanup;
3982 3983
    }

3984
    if (virStoragePoolObjIsActive(privpool)) {
3985
        testError(VIR_ERR_OPERATION_INVALID,
3986 3987 3988
                  _("storage pool '%s' is already active"), pool->name);
        goto cleanup;
    }
C
Cole Robinson 已提交
3989 3990

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

3993
cleanup:
3994 3995 3996
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
3997
    return ret;
C
Cole Robinson 已提交
3998 3999 4000
}

static int
4001
testStoragePoolBuild(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4002
                     unsigned int flags ATTRIBUTE_UNUSED) {
4003 4004
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4005
    int ret = -1;
4006

4007
    testDriverLock(privconn);
4008 4009
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4010
    testDriverUnlock(privconn);
4011 4012

    if (privpool == NULL) {
4013
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4014
        goto cleanup;
4015 4016
    }

4017
    if (virStoragePoolObjIsActive(privpool)) {
4018
        testError(VIR_ERR_OPERATION_INVALID,
4019 4020 4021
                  _("storage pool '%s' is already active"), pool->name);
        goto cleanup;
    }
4022
    ret = 0;
C
Cole Robinson 已提交
4023

4024
cleanup:
4025 4026
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4027
    return ret;
C
Cole Robinson 已提交
4028 4029 4030 4031
}


static int
4032 4033 4034
testStoragePoolDestroy(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4035
    int ret = -1;
4036

4037
    testDriverLock(privconn);
4038 4039 4040 4041
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);

    if (privpool == NULL) {
4042
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4043
        goto cleanup;
4044 4045 4046
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4047
        testError(VIR_ERR_OPERATION_INVALID,
4048
                  _("storage pool '%s' is not active"), pool->name);
4049
        goto cleanup;
4050
    }
C
Cole Robinson 已提交
4051 4052 4053

    privpool->active = 0;

4054
    if (privpool->configFile == NULL) {
C
Cole Robinson 已提交
4055
        virStoragePoolObjRemove(&privconn->pools, privpool);
4056 4057
        privpool = NULL;
    }
4058
    ret = 0;
C
Cole Robinson 已提交
4059

4060
cleanup:
4061 4062 4063
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    testDriverUnlock(privconn);
4064
    return ret;
C
Cole Robinson 已提交
4065 4066 4067 4068
}


static int
4069
testStoragePoolDelete(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4070
                      unsigned int flags ATTRIBUTE_UNUSED) {
4071 4072
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4073
    int ret = -1;
4074

4075
    testDriverLock(privconn);
4076 4077
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4078
    testDriverUnlock(privconn);
4079 4080

    if (privpool == NULL) {
4081
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4082 4083 4084 4085
        goto cleanup;
    }

    if (virStoragePoolObjIsActive(privpool)) {
4086
        testError(VIR_ERR_OPERATION_INVALID,
4087 4088
                  _("storage pool '%s' is already active"), pool->name);
        goto cleanup;
4089 4090
    }

4091
    ret = 0;
C
Cole Robinson 已提交
4092

4093
cleanup:
4094 4095
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4096
    return ret;
C
Cole Robinson 已提交
4097 4098 4099 4100
}


static int
4101
testStoragePoolRefresh(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4102
                       unsigned int flags ATTRIBUTE_UNUSED) {
4103 4104
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4105
    int ret = -1;
4106

4107
    testDriverLock(privconn);
4108 4109
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4110
    testDriverUnlock(privconn);
4111 4112

    if (privpool == NULL) {
4113
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4114
        goto cleanup;
4115 4116 4117
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4118
        testError(VIR_ERR_OPERATION_INVALID,
4119
                  _("storage pool '%s' is not active"), pool->name);
4120
        goto cleanup;
4121
    }
4122
    ret = 0;
C
Cole Robinson 已提交
4123

4124
cleanup:
4125 4126
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4127
    return ret;
C
Cole Robinson 已提交
4128 4129 4130 4131
}


static int
4132
testStoragePoolGetInfo(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4133
                       virStoragePoolInfoPtr info) {
4134 4135
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4136
    int ret = -1;
4137

4138
    testDriverLock(privconn);
4139 4140
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4141
    testDriverUnlock(privconn);
4142 4143

    if (privpool == NULL) {
4144
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4145
        goto cleanup;
4146
    }
C
Cole Robinson 已提交
4147 4148 4149 4150 4151 4152 4153 4154 4155

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

4158
cleanup:
4159 4160
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4161
    return ret;
C
Cole Robinson 已提交
4162 4163 4164
}

static char *
4165
testStoragePoolDumpXML(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4166
                       unsigned int flags ATTRIBUTE_UNUSED) {
4167 4168
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4169
    char *ret = NULL;
4170

4171
    testDriverLock(privconn);
4172 4173
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4174
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4175

4176
    if (privpool == NULL) {
4177
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4178
        goto cleanup;
4179 4180
    }

4181
    ret = virStoragePoolDefFormat(privpool->def);
4182 4183

cleanup:
4184 4185
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4186
    return ret;
C
Cole Robinson 已提交
4187 4188 4189
}

static int
4190
testStoragePoolGetAutostart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4191
                            int *autostart) {
4192 4193
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4194
    int ret = -1;
4195

4196
    testDriverLock(privconn);
4197 4198
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4199
    testDriverUnlock(privconn);
4200 4201

    if (privpool == NULL) {
4202
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4203
        goto cleanup;
4204
    }
C
Cole Robinson 已提交
4205 4206 4207 4208 4209 4210

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

4213
cleanup:
4214 4215
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4216
    return ret;
C
Cole Robinson 已提交
4217 4218 4219
}

static int
4220
testStoragePoolSetAutostart(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4221
                            int autostart) {
4222 4223
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4224
    int ret = -1;
4225

4226
    testDriverLock(privconn);
4227 4228
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4229
    testDriverUnlock(privconn);
4230 4231

    if (privpool == NULL) {
4232
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4233
        goto cleanup;
4234
    }
C
Cole Robinson 已提交
4235 4236

    if (!privpool->configFile) {
4237
        testError(VIR_ERR_INVALID_ARG,
C
Cole Robinson 已提交
4238
                  "%s", _("pool has no config file"));
4239
        goto cleanup;
C
Cole Robinson 已提交
4240 4241 4242 4243
    }

    autostart = (autostart != 0);
    privpool->autostart = autostart;
4244 4245 4246
    ret = 0;

cleanup:
4247 4248
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4249
    return ret;
C
Cole Robinson 已提交
4250 4251 4252 4253
}


static int
4254 4255 4256
testStoragePoolNumVolumes(virStoragePoolPtr pool) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4257
    int ret = -1;
4258

4259
    testDriverLock(privconn);
4260 4261
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4262
    testDriverUnlock(privconn);
4263 4264

    if (privpool == NULL) {
4265
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4266
        goto cleanup;
4267 4268 4269
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4270
        testError(VIR_ERR_OPERATION_INVALID,
4271
                  _("storage pool '%s' is not active"), pool->name);
4272
        goto cleanup;
4273
    }
C
Cole Robinson 已提交
4274

4275 4276 4277
    ret = privpool->volumes.count;

cleanup:
4278 4279
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4280
    return ret;
C
Cole Robinson 已提交
4281 4282 4283
}

static int
4284
testStoragePoolListVolumes(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4285 4286
                           char **const names,
                           int maxnames) {
4287 4288
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
C
Cole Robinson 已提交
4289 4290
    int i = 0, n = 0;

4291
    memset(names, 0, maxnames * sizeof(*names));
4292 4293

    testDriverLock(privconn);
4294 4295
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4296
    testDriverUnlock(privconn);
4297 4298

    if (privpool == NULL) {
4299
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4300
        goto cleanup;
4301 4302 4303 4304
    }


    if (!virStoragePoolObjIsActive(privpool)) {
4305
        testError(VIR_ERR_OPERATION_INVALID,
4306
                  _("storage pool '%s' is not active"), pool->name);
4307
        goto cleanup;
4308 4309
    }

C
Cole Robinson 已提交
4310 4311
    for (i = 0 ; i < privpool->volumes.count && n < maxnames ; i++) {
        if ((names[n++] = strdup(privpool->volumes.objs[i]->name)) == NULL) {
4312
            virReportOOMError();
C
Cole Robinson 已提交
4313 4314 4315 4316
            goto cleanup;
        }
    }

4317
    virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4318 4319 4320 4321 4322 4323
    return n;

 cleanup:
    for (n = 0 ; n < maxnames ; n++)
        VIR_FREE(names[i]);

4324
    memset(names, 0, maxnames * sizeof(*names));
4325 4326
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4327 4328 4329 4330 4331
    return -1;
}


static virStorageVolPtr
4332
testStorageVolumeLookupByName(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4333
                              const char *name ATTRIBUTE_UNUSED) {
4334 4335 4336
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
4337
    virStorageVolPtr ret = NULL;
4338

4339
    testDriverLock(privconn);
4340 4341
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4342
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4343

4344
    if (privpool == NULL) {
4345
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4346
        goto cleanup;
4347 4348 4349 4350
    }


    if (!virStoragePoolObjIsActive(privpool)) {
4351
        testError(VIR_ERR_OPERATION_INVALID,
4352
                  _("storage pool '%s' is not active"), pool->name);
4353
        goto cleanup;
4354 4355 4356 4357 4358
    }

    privvol = virStorageVolDefFindByName(privpool, name);

    if (!privvol) {
4359
        testError(VIR_ERR_NO_STORAGE_VOL,
C
Cole Robinson 已提交
4360
                  _("no storage vol with matching name '%s'"), name);
4361
        goto cleanup;
C
Cole Robinson 已提交
4362 4363
    }

4364 4365 4366 4367
    ret = virGetStorageVol(pool->conn, privpool->def->name,
                           privvol->name, privvol->key);

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


static virStorageVolPtr
testStorageVolumeLookupByKey(virConnectPtr conn,
                             const char *key) {
4377
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4378
    unsigned int i;
4379
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4380

4381
    testDriverLock(privconn);
C
Cole Robinson 已提交
4382
    for (i = 0 ; i < privconn->pools.count ; i++) {
4383
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4384
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4385
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4386 4387
                virStorageVolDefFindByKey(privconn->pools.objs[i], key);

4388 4389 4390 4391 4392
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
                                       privvol->key);
4393
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
4394 4395
                break;
            }
C
Cole Robinson 已提交
4396
        }
4397
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4398
    }
4399
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4400

4401
    if (!ret)
4402
        testError(VIR_ERR_NO_STORAGE_VOL,
4403 4404 4405
                  _("no storage vol with matching key '%s'"), key);

    return ret;
C
Cole Robinson 已提交
4406 4407 4408 4409 4410
}

static virStorageVolPtr
testStorageVolumeLookupByPath(virConnectPtr conn,
                              const char *path) {
4411
    testConnPtr privconn = conn->privateData;
C
Cole Robinson 已提交
4412
    unsigned int i;
4413
    virStorageVolPtr ret = NULL;
C
Cole Robinson 已提交
4414

4415
    testDriverLock(privconn);
C
Cole Robinson 已提交
4416
    for (i = 0 ; i < privconn->pools.count ; i++) {
4417
        virStoragePoolObjLock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4418
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
4419
            virStorageVolDefPtr privvol =
C
Cole Robinson 已提交
4420 4421
                virStorageVolDefFindByPath(privconn->pools.objs[i], path);

4422 4423 4424 4425 4426
            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name,
                                       privvol->key);
4427
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
4428 4429
                break;
            }
C
Cole Robinson 已提交
4430
        }
4431
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
C
Cole Robinson 已提交
4432
    }
4433
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4434

4435
    if (!ret)
4436
        testError(VIR_ERR_NO_STORAGE_VOL,
4437 4438 4439
                  _("no storage vol with matching path '%s'"), path);

    return ret;
C
Cole Robinson 已提交
4440 4441 4442
}

static virStorageVolPtr
4443
testStorageVolumeCreateXML(virStoragePoolPtr pool,
C
Cole Robinson 已提交
4444 4445
                           const char *xmldesc,
                           unsigned int flags ATTRIBUTE_UNUSED) {
4446 4447
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
4448 4449
    virStorageVolDefPtr privvol = NULL;
    virStorageVolPtr ret = NULL;
4450

4451
    testDriverLock(privconn);
4452 4453
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
4454
    testDriverUnlock(privconn);
C
Cole Robinson 已提交
4455

4456
    if (privpool == NULL) {
4457
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4458
        goto cleanup;
4459 4460 4461
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4462
        testError(VIR_ERR_OPERATION_INVALID,
4463
                  _("storage pool '%s' is not active"), pool->name);
4464
        goto cleanup;
4465
    }
C
Cole Robinson 已提交
4466

4467
    privvol = virStorageVolDefParseString(privpool->def, xmldesc);
4468
    if (privvol == NULL)
4469
        goto cleanup;
4470 4471

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
4472
        testError(VIR_ERR_OPERATION_FAILED,
C
Cole Robinson 已提交
4473
                  "%s", _("storage vol already exists"));
4474
        goto cleanup;
C
Cole Robinson 已提交
4475 4476 4477
    }

    /* Make sure enough space */
4478
    if ((privpool->def->allocation + privvol->allocation) >
C
Cole Robinson 已提交
4479
         privpool->def->capacity) {
4480
        testError(VIR_ERR_INTERNAL_ERROR,
C
Cole Robinson 已提交
4481
                  _("Not enough free space in pool for volume '%s'"),
4482
                  privvol->name);
4483
        goto cleanup;
C
Cole Robinson 已提交
4484 4485 4486 4487
    }

    if (VIR_REALLOC_N(privpool->volumes.objs,
                      privpool->volumes.count+1) < 0) {
4488
        virReportOOMError();
4489
        goto cleanup;
C
Cole Robinson 已提交
4490 4491
    }

4492 4493 4494
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
                    privvol->name) == -1) {
4495
        virReportOOMError();
4496
        goto cleanup;
C
Cole Robinson 已提交
4497 4498
    }

4499 4500
    privvol->key = strdup(privvol->target.path);
    if (privvol->key == NULL) {
4501
        virReportOOMError();
4502
        goto cleanup;
C
Cole Robinson 已提交
4503 4504
    }

4505
    privpool->def->allocation += privvol->allocation;
C
Cole Robinson 已提交
4506 4507 4508
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

4509
    privpool->volumes.objs[privpool->volumes.count++] = privvol;
C
Cole Robinson 已提交
4510

4511 4512
    ret = virGetStorageVol(pool->conn, privpool->def->name,
                           privvol->name, privvol->key);
4513
    privvol = NULL;
4514 4515 4516

cleanup:
    virStorageVolDefFree(privvol);
4517 4518
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4519
    return ret;
C
Cole Robinson 已提交
4520 4521
}

4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537
static virStorageVolPtr
testStorageVolumeCreateXMLFrom(virStoragePoolPtr pool,
                               const char *xmldesc,
                               virStorageVolPtr clonevol,
                               unsigned int flags ATTRIBUTE_UNUSED) {
    testConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol = NULL, origvol = NULL;
    virStorageVolPtr ret = NULL;

    testDriverLock(privconn);
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           pool->name);
    testDriverUnlock(privconn);

    if (privpool == NULL) {
4538
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4539 4540 4541 4542
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4543
        testError(VIR_ERR_OPERATION_INVALID,
4544 4545 4546 4547
                  _("storage pool '%s' is not active"), pool->name);
        goto cleanup;
    }

4548
    privvol = virStorageVolDefParseString(privpool->def, xmldesc);
4549 4550 4551 4552
    if (privvol == NULL)
        goto cleanup;

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
4553
        testError(VIR_ERR_OPERATION_FAILED,
4554 4555 4556 4557 4558 4559
                  "%s", _("storage vol already exists"));
        goto cleanup;
    }

    origvol = virStorageVolDefFindByName(privpool, clonevol->name);
    if (!origvol) {
4560
        testError(VIR_ERR_NO_STORAGE_VOL,
4561 4562 4563 4564 4565 4566 4567 4568
                  _("no storage vol with matching name '%s'"),
                  clonevol->name);
        goto cleanup;
    }

    /* Make sure enough space */
    if ((privpool->def->allocation + privvol->allocation) >
         privpool->def->capacity) {
4569
        testError(VIR_ERR_INTERNAL_ERROR,
4570 4571 4572 4573 4574 4575 4576 4577 4578
                  _("Not enough free space in pool for volume '%s'"),
                  privvol->name);
        goto cleanup;
    }
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    if (VIR_REALLOC_N(privpool->volumes.objs,
                      privpool->volumes.count+1) < 0) {
4579
        virReportOOMError();
4580 4581 4582
        goto cleanup;
    }

4583 4584 4585
    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path,
                    privvol->name) == -1) {
4586
        virReportOOMError();
4587 4588 4589 4590 4591
        goto cleanup;
    }

    privvol->key = strdup(privvol->target.path);
    if (privvol->key == NULL) {
4592
        virReportOOMError();
4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612
        goto cleanup;
    }

    privpool->def->allocation += privvol->allocation;
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    privpool->volumes.objs[privpool->volumes.count++] = privvol;

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

cleanup:
    virStorageVolDefFree(privvol);
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    return ret;
}

C
Cole Robinson 已提交
4613
static int
4614
testStorageVolumeDelete(virStorageVolPtr vol,
C
Cole Robinson 已提交
4615
                        unsigned int flags ATTRIBUTE_UNUSED) {
4616 4617 4618
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
C
Cole Robinson 已提交
4619
    int i;
4620
    int ret = -1;
C
Cole Robinson 已提交
4621

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

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


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

    if (privvol == NULL) {
4636
        testError(VIR_ERR_NO_STORAGE_VOL,
4637 4638
                  _("no storage vol with matching name '%s'"),
                  vol->name);
4639
        goto cleanup;
4640 4641 4642
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4643
        testError(VIR_ERR_OPERATION_INVALID,
4644
                  _("storage pool '%s' is not active"), vol->pool);
4645
        goto cleanup;
4646 4647 4648
    }


C
Cole Robinson 已提交
4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671
    privpool->def->allocation -= privvol->allocation;
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    for (i = 0 ; i < privpool->volumes.count ; i++) {
        if (privpool->volumes.objs[i] == privvol) {
            virStorageVolDefFree(privvol);

            if (i < (privpool->volumes.count - 1))
                memmove(privpool->volumes.objs + i,
                        privpool->volumes.objs + i + 1,
                        sizeof(*(privpool->volumes.objs)) *
                                (privpool->volumes.count - (i + 1)));

            if (VIR_REALLOC_N(privpool->volumes.objs,
                              privpool->volumes.count - 1) < 0) {
                ; /* Failure to reduce memory allocation isn't fatal */
            }
            privpool->volumes.count--;

            break;
        }
    }
4672
    ret = 0;
C
Cole Robinson 已提交
4673

4674
cleanup:
4675 4676
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4677
    return ret;
C
Cole Robinson 已提交
4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693
}


static int testStorageVolumeTypeForPool(int pooltype) {

    switch(pooltype) {
        case VIR_STORAGE_POOL_DIR:
        case VIR_STORAGE_POOL_FS:
        case VIR_STORAGE_POOL_NETFS:
            return VIR_STORAGE_VOL_FILE;
        default:
            return VIR_STORAGE_VOL_BLOCK;
    }
}

static int
4694
testStorageVolumeGetInfo(virStorageVolPtr vol,
C
Cole Robinson 已提交
4695
                         virStorageVolInfoPtr info) {
4696 4697 4698
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
4699
    int ret = -1;
4700

4701
    testDriverLock(privconn);
4702 4703
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
4704
    testDriverUnlock(privconn);
4705 4706

    if (privpool == NULL) {
4707
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4708
        goto cleanup;
4709 4710 4711 4712 4713
    }

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

    if (privvol == NULL) {
4714
        testError(VIR_ERR_NO_STORAGE_VOL,
4715 4716
                  _("no storage vol with matching name '%s'"),
                  vol->name);
4717
        goto cleanup;
4718 4719 4720
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4721
        testError(VIR_ERR_OPERATION_INVALID,
4722
                  _("storage pool '%s' is not active"), vol->pool);
4723
        goto cleanup;
4724
    }
C
Cole Robinson 已提交
4725 4726 4727 4728 4729

    memset(info, 0, sizeof(*info));
    info->type = testStorageVolumeTypeForPool(privpool->def->type);
    info->capacity = privvol->capacity;
    info->allocation = privvol->allocation;
4730
    ret = 0;
C
Cole Robinson 已提交
4731

4732
cleanup:
4733 4734
    if (privpool)
        virStoragePoolObjUnlock(privpool);
4735
    return ret;
C
Cole Robinson 已提交
4736 4737 4738
}

static char *
4739
testStorageVolumeGetXMLDesc(virStorageVolPtr vol,
C
Cole Robinson 已提交
4740
                            unsigned int flags ATTRIBUTE_UNUSED) {
4741 4742 4743
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
4744
    char *ret = NULL;
4745

4746
    testDriverLock(privconn);
4747 4748
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
4749
    testDriverUnlock(privconn);
4750 4751

    if (privpool == NULL) {
4752
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4753
        goto cleanup;
4754 4755 4756 4757 4758
    }

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

    if (privvol == NULL) {
4759
        testError(VIR_ERR_NO_STORAGE_VOL,
4760 4761
                  _("no storage vol with matching name '%s'"),
                  vol->name);
4762
        goto cleanup;
4763
    }
C
Cole Robinson 已提交
4764

4765
    if (!virStoragePoolObjIsActive(privpool)) {
4766
        testError(VIR_ERR_OPERATION_INVALID,
4767
                  _("storage pool '%s' is not active"), vol->pool);
4768
        goto cleanup;
4769 4770
    }

4771
    ret = virStorageVolDefFormat(privpool->def, privvol);
4772 4773

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

static char *
4780 4781 4782 4783
testStorageVolumeGetPath(virStorageVolPtr vol) {
    testConnPtr privconn = vol->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
4784
    char *ret = NULL;
4785

4786
    testDriverLock(privconn);
4787 4788
    privpool = virStoragePoolObjFindByName(&privconn->pools,
                                           vol->pool);
4789
    testDriverUnlock(privconn);
4790 4791

    if (privpool == NULL) {
4792
        testError(VIR_ERR_INVALID_ARG, __FUNCTION__);
4793
        goto cleanup;
4794 4795 4796 4797 4798
    }

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

    if (privvol == NULL) {
4799
        testError(VIR_ERR_NO_STORAGE_VOL,
4800 4801
                  _("no storage vol with matching name '%s'"),
                  vol->name);
4802
        goto cleanup;
4803 4804 4805
    }

    if (!virStoragePoolObjIsActive(privpool)) {
4806
        testError(VIR_ERR_OPERATION_INVALID,
4807
                  _("storage pool '%s' is not active"), vol->pool);
4808
        goto cleanup;
4809 4810
    }

C
Cole Robinson 已提交
4811
    ret = strdup(privvol->target.path);
4812
    if (ret == NULL)
4813
        virReportOOMError();
4814 4815

cleanup:
4816 4817
    if (privpool)
        virStoragePoolObjUnlock(privpool);
C
Cole Robinson 已提交
4818 4819 4820
    return ret;
}

4821

4822
/* Node device implementations */
4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837
static virDrvOpenStatus testDevMonOpen(virConnectPtr conn,
                                       virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                       int flags ATTRIBUTE_UNUSED) {
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

    conn->devMonPrivateData = conn->privateData;
    return VIR_DRV_OPEN_SUCCESS;
}

static int testDevMonClose(virConnectPtr conn) {
    conn->devMonPrivateData = NULL;
    return 0;
}

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 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903
static int
testNodeNumOfDevices(virConnectPtr conn,
                     const char *cap,
                     unsigned int flags ATTRIBUTE_UNUSED)
{
    testConnPtr driver = conn->privateData;
    int ndevs = 0;
    unsigned int i;

    testDriverLock(driver);
    for (i = 0; i < driver->devs.count; i++)
        if ((cap == NULL) ||
            virNodeDeviceHasCap(driver->devs.objs[i], cap))
            ++ndevs;
    testDriverUnlock(driver);

    return ndevs;
}

static int
testNodeListDevices(virConnectPtr conn,
                    const char *cap,
                    char **const names,
                    int maxnames,
                    unsigned int flags ATTRIBUTE_UNUSED)
{
    testConnPtr driver = conn->privateData;
    int ndevs = 0;
    unsigned int i;

    testDriverLock(driver);
    for (i = 0; i < driver->devs.count && ndevs < maxnames; i++) {
        virNodeDeviceObjLock(driver->devs.objs[i]);
        if (cap == NULL ||
            virNodeDeviceHasCap(driver->devs.objs[i], cap)) {
            if ((names[ndevs++] = strdup(driver->devs.objs[i]->def->name)) == NULL) {
                virNodeDeviceObjUnlock(driver->devs.objs[i]);
                goto failure;
            }
        }
        virNodeDeviceObjUnlock(driver->devs.objs[i]);
    }
    testDriverUnlock(driver);

    return ndevs;

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

static virNodeDevicePtr
testNodeDeviceLookupByName(virConnectPtr conn, const char *name)
{
    testConnPtr driver = conn->privateData;
    virNodeDeviceObjPtr obj;
    virNodeDevicePtr ret = NULL;

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

    if (!obj) {
4904
        virNodeDeviceReportError(VIR_ERR_NO_NODE_DEVICE, NULL);
4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928
        goto cleanup;
    }

    ret = virGetNodeDevice(conn, name);

cleanup:
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

static char *
testNodeDeviceDumpXML(virNodeDevicePtr dev,
                      unsigned int flags ATTRIBUTE_UNUSED)
{
    testConnPtr driver = dev->conn->privateData;
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

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

    if (!obj) {
4929 4930
        virNodeDeviceReportError(VIR_ERR_NO_NODE_DEVICE,
                                 _("no node device with matching name '%s'"),
4931 4932 4933 4934
                                 dev->name);
        goto cleanup;
    }

4935
    ret = virNodeDeviceDefFormat(obj->def);
4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954

cleanup:
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

static char *
testNodeDeviceGetParent(virNodeDevicePtr dev)
{
    testConnPtr driver = dev->conn->privateData;
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

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

    if (!obj) {
4955
        virNodeDeviceReportError(VIR_ERR_NO_NODE_DEVICE,
4956 4957 4958 4959 4960 4961 4962 4963
                                _("no node device with matching name '%s'"),
                                 dev->name);
        goto cleanup;
    }

    if (obj->def->parent) {
        ret = strdup(obj->def->parent);
        if (!ret)
4964
            virReportOOMError();
4965
    } else {
4966
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
4967 4968 4969 4970 4971 4972 4973 4974 4975
                                 "%s", _("no parent for this device"));
    }

cleanup:
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}

4976

4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990
static int
testNodeDeviceNumOfCaps(virNodeDevicePtr dev)
{
    testConnPtr driver = dev->conn->privateData;
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

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

    if (!obj) {
4991 4992
        virNodeDeviceReportError(VIR_ERR_NO_NODE_DEVICE,
                                 _("no node device with matching name '%s'"),
4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021
                                 dev->name);
        goto cleanup;
    }

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

cleanup:
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}


static int
testNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
    testConnPtr driver = dev->conn->privateData;
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

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

    if (!obj) {
5022
        virNodeDeviceReportError(VIR_ERR_NO_NODE_DEVICE,
5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045
                                _("no node device with matching name '%s'"),
                                 dev->name);
        goto cleanup;
    }

    for (caps = obj->def->caps; caps && ncaps < maxnames; caps = caps->next) {
        names[ncaps] = strdup(virNodeDevCapTypeToString(caps->type));
        if (names[ncaps++] == NULL)
            goto cleanup;
    }
    ret = ncaps;

cleanup:
    if (obj)
        virNodeDeviceObjUnlock(obj);
    if (ret == -1) {
        --ncaps;
        while (--ncaps >= 0)
            VIR_FREE(names[ncaps]);
    }
    return ret;
}

5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060
static virNodeDevicePtr
testNodeDeviceCreateXML(virConnectPtr conn,
                        const char *xmlDesc,
                        unsigned int flags ATTRIBUTE_UNUSED)
{
    testConnPtr driver = conn->privateData;
    virNodeDeviceDefPtr def = NULL;
    virNodeDeviceObjPtr obj = NULL;
    char *wwnn = NULL, *wwpn = NULL;
    int parent_host = -1;
    virNodeDevicePtr dev = NULL;
    virNodeDevCapsDefPtr caps;

    testDriverLock(driver);

5061
    def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE);
5062 5063 5064 5065 5066
    if (def == NULL) {
        goto cleanup;
    }

    /* We run these next two simply for validation */
5067
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) == -1) {
5068 5069 5070
        goto cleanup;
    }

5071
    if (virNodeDeviceGetParentHost(&driver->devs,
5072 5073 5074 5075 5076 5077 5078 5079 5080 5081
                                   def->name,
                                   def->parent,
                                   &parent_host) == -1) {
        goto cleanup;
    }

    /* 'name' is supposed to be filled in by the node device backend, which
     * we don't have. Use WWPN instead. */
    VIR_FREE(def->name);
    if (!(def->name = strdup(wwpn))) {
5082
        virReportOOMError();
5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097
        goto cleanup;
    }

    /* Fill in a random 'host' value, since this would also come from
     * the backend */
    caps = def->caps;
    while (caps) {
        if (caps->type != VIR_NODE_DEV_CAP_SCSI_HOST)
            continue;

        caps->data.scsi_host.host = virRandom(1024);
        caps = caps->next;
    }


5098
    if (!(obj = virNodeDeviceAssignDef(&driver->devs, def))) {
5099 5100 5101 5102 5103 5104 5105 5106
        goto cleanup;
    }
    virNodeDeviceObjUnlock(obj);

    dev = virGetNodeDevice(conn, def->name);
    def = NULL;
cleanup:
    testDriverUnlock(driver);
5107
    virNodeDeviceDefFree(def);
5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return dev;
}

static int
testNodeDeviceDestroy(virNodeDevicePtr dev)
{
    int ret = 0;
    testConnPtr driver = dev->conn->privateData;
    virNodeDeviceObjPtr obj = NULL;
    char *parent_name = NULL, *wwnn = NULL, *wwpn = NULL;
    int parent_host = -1;

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

    if (!obj) {
5127
        virNodeDeviceReportError(VIR_ERR_NO_NODE_DEVICE, NULL);
5128 5129 5130
        goto out;
    }

5131
    if (virNodeDeviceGetWWNs(obj->def, &wwnn, &wwpn) == -1) {
5132 5133 5134 5135 5136
        goto out;
    }

    parent_name = strdup(obj->def->parent);
    if (parent_name == NULL) {
5137
        virReportOOMError();
5138 5139 5140 5141 5142 5143 5144 5145 5146 5147
        goto out;
    }

    /* virNodeDeviceGetParentHost will cause the device object's lock to be
     * taken, so we have to dup the parent's name and drop the lock
     * before calling it.  We don't need the reference to the object
     * any more once we have the parent's name.  */
    virNodeDeviceObjUnlock(obj);

    /* We do this just for basic validation */
5148
    if (virNodeDeviceGetParentHost(&driver->devs,
5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167
                                   dev->name,
                                   parent_name,
                                   &parent_host) == -1) {
        obj = NULL;
        goto out;
    }

    virNodeDeviceObjLock(obj);
    virNodeDeviceObjRemove(&driver->devs, obj);

out:
    if (obj)
        virNodeDeviceObjUnlock(obj);
    VIR_FREE(parent_name);
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return ret;
}

5168 5169

/* Domain event implementations */
5170
static int
5171 5172 5173 5174
testDomainEventRegister(virConnectPtr conn,
                        virConnectDomainEventCallback callback,
                        void *opaque,
                        virFreeCallback freecb)
5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
    ret = virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks,
                                        callback, opaque, freecb);
    testDriverUnlock(driver);

    return ret;
}

5187

5188
static int
5189 5190
testDomainEventDeregister(virConnectPtr conn,
                          virConnectDomainEventCallback callback)
5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
    if (driver->domainEventDispatching)
        ret = virDomainEventCallbackListMarkDelete(conn, driver->domainEventCallbacks,
                                                   callback);
    else
        ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks,
                                               callback);
    testDriverUnlock(driver);

    return ret;
}

5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247

static int
testDomainEventRegisterAny(virConnectPtr conn,
                           virDomainPtr dom,
                           int eventID,
                           virConnectDomainEventGenericCallback callback,
                           void *opaque,
                           virFreeCallback freecb)
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
    ret = virDomainEventCallbackListAddID(conn, driver->domainEventCallbacks,
                                          dom, eventID,
                                          callback, opaque, freecb);
    testDriverUnlock(driver);

    return ret;
}

static int
testDomainEventDeregisterAny(virConnectPtr conn,
                             int callbackID)
{
    testConnPtr driver = conn->privateData;
    int ret;

    testDriverLock(driver);
    if (driver->domainEventDispatching)
        ret = virDomainEventCallbackListMarkDeleteID(conn, driver->domainEventCallbacks,
                                                     callbackID);
    else
        ret = virDomainEventCallbackListRemoveID(conn, driver->domainEventCallbacks,
                                                 callbackID);
    testDriverUnlock(driver);

    return ret;
}


5248 5249
static void testDomainEventDispatchFunc(virConnectPtr conn,
                                        virDomainEventPtr event,
5250
                                        virConnectDomainEventGenericCallback cb,
5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307
                                        void *cbopaque,
                                        void *opaque)
{
    testConnPtr driver = opaque;

    /* Drop the lock whle dispatching, for sake of re-entrancy */
    testDriverUnlock(driver);
    virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL);
    testDriverLock(driver);
}

static void testDomainEventFlush(int timer ATTRIBUTE_UNUSED, void *opaque)
{
    testConnPtr driver = opaque;
    virDomainEventQueue tempQueue;

    testDriverLock(driver);

    driver->domainEventDispatching = 1;

    /* Copy the queue, so we're reentrant safe */
    tempQueue.count = driver->domainEventQueue->count;
    tempQueue.events = driver->domainEventQueue->events;
    driver->domainEventQueue->count = 0;
    driver->domainEventQueue->events = NULL;

    virEventUpdateTimeout(driver->domainEventTimer, -1);
    virDomainEventQueueDispatch(&tempQueue,
                                driver->domainEventCallbacks,
                                testDomainEventDispatchFunc,
                                driver);

    /* Purge any deleted callbacks */
    virDomainEventCallbackListPurgeMarked(driver->domainEventCallbacks);

    driver->domainEventDispatching = 0;
    testDriverUnlock(driver);
}


/* driver must be locked before calling */
static void testDomainEventQueue(testConnPtr driver,
                                 virDomainEventPtr event)
{
    if (driver->domainEventTimer < 0) {
        virDomainEventFree(event);
        return;
    }

    if (virDomainEventQueuePush(driver->domainEventQueue,
                                event) < 0)
        virDomainEventFree(event);

    if (driver->domainEventQueue->count == 1)
        virEventUpdateTimeout(driver->domainEventTimer, 0);
}

5308 5309 5310 5311 5312 5313
static virDrvOpenStatus testSecretOpen(virConnectPtr conn,
                                       virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                       int flags ATTRIBUTE_UNUSED) {
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

5314
    conn->secretPrivateData = conn->privateData;
5315 5316 5317 5318 5319 5320 5321
    return VIR_DRV_OPEN_SUCCESS;
}

static int testSecretClose(virConnectPtr conn) {
    conn->secretPrivateData = NULL;
    return 0;
}
5322

5323 5324 5325 5326 5327 5328 5329

static virDrvOpenStatus testNWFilterOpen(virConnectPtr conn,
                                         virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                         int flags ATTRIBUTE_UNUSED) {
    if (STRNEQ(conn->driver->name, "Test"))
        return VIR_DRV_OPEN_DECLINED;

5330
    conn->nwfilterPrivateData = conn->privateData;
5331 5332 5333 5334 5335 5336 5337 5338
    return VIR_DRV_OPEN_SUCCESS;
}

static int testNWFilterClose(virConnectPtr conn) {
    conn->nwfilterPrivateData = NULL;
    return 0;
}

5339 5340 5341 5342 5343
static virDriver testDriver = {
    VIR_DRV_TEST,
    "Test",
    testOpen, /* open */
    testClose, /* close */
5344
    NULL, /* supports_feature */
5345 5346
    NULL, /* type */
    testGetVersion, /* version */
5347
    NULL, /* libvirtVersion (impl. in libvirt.c) */
5348
    virGetHostname, /* getHostname */
E
Eric Blake 已提交
5349
    NULL, /* getSysinfo */
5350 5351 5352 5353 5354
    testGetMaxVCPUs, /* getMaxVcpus */
    testNodeGetInfo, /* nodeGetInfo */
    testGetCapabilities, /* getCapabilities */
    testListDomains, /* listDomains */
    testNumOfDomains, /* numOfDomains */
5355
    testDomainCreateXML, /* domainCreateXML */
5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367
    testLookupDomainByID, /* domainLookupByID */
    testLookupDomainByUUID, /* domainLookupByUUID */
    testLookupDomainByName, /* domainLookupByName */
    testPauseDomain, /* domainSuspend */
    testResumeDomain, /* domainResume */
    testShutdownDomain, /* domainShutdown */
    testRebootDomain, /* domainReboot */
    testDestroyDomain, /* domainDestroy */
    testGetOSType, /* domainGetOSType */
    testGetMaxMemory, /* domainGetMaxMemory */
    testSetMaxMemory, /* domainSetMaxMemory */
    testSetMemory, /* domainSetMemory */
5368
    NULL, /* domainSetMemoryFlags */
5369 5370 5371 5372
    NULL, /* domainSetMemoryParameters */
    NULL, /* domainGetMemoryParameters */
    NULL, /* domainSetBlkioParameters */
    NULL, /* domainGetBlkioParameters */
5373 5374 5375 5376 5377
    testGetDomainInfo, /* domainGetInfo */
    testDomainSave, /* domainSave */
    testDomainRestore, /* domainRestore */
    testDomainCoreDump, /* domainCoreDump */
    testSetVcpus, /* domainSetVcpus */
5378 5379
    testDomainSetVcpusFlags, /* domainSetVcpusFlags */
    testDomainGetVcpusFlags, /* domainGetVcpusFlags */
C
Cole Robinson 已提交
5380
    testDomainPinVcpu, /* domainPinVcpu */
C
Cole Robinson 已提交
5381
    testDomainGetVcpus, /* domainGetVcpus */
C
Cole Robinson 已提交
5382
    testDomainGetMaxVcpus, /* domainGetMaxVcpus */
5383 5384
    NULL, /* domainGetSecurityLabel */
    NULL, /* nodeGetSecurityModel */
5385
    testDomainDumpXML, /* domainDumpXML */
5386 5387
    NULL, /* domainXMLFromNative */
    NULL, /* domainXMLToNative */
5388 5389 5390
    testListDefinedDomains, /* listDefinedDomains */
    testNumOfDefinedDomains, /* numOfDefinedDomains */
    testDomainCreate, /* domainCreate */
5391
    testDomainCreateWithFlags, /* domainCreateWithFlags */
5392 5393 5394
    testDomainDefineXML, /* domainDefineXML */
    testDomainUndefine, /* domainUndefine */
    NULL, /* domainAttachDevice */
5395
    NULL, /* domainAttachDeviceFlags */
5396
    NULL, /* domainDetachDevice */
5397
    NULL, /* domainDetachDeviceFlags */
5398
    NULL, /* domainUpdateDeviceFlags */
5399 5400 5401 5402 5403
    testDomainGetAutostart, /* domainGetAutostart */
    testDomainSetAutostart, /* domainSetAutostart */
    testDomainGetSchedulerType, /* domainGetSchedulerType */
    testDomainGetSchedulerParams, /* domainGetSchedulerParameters */
    testDomainSetSchedulerParams, /* domainSetSchedulerParameters */
5404 5405 5406
    NULL, /* domainMigratePrepare */
    NULL, /* domainMigratePerform */
    NULL, /* domainMigrateFinish */
5407 5408
    testDomainBlockStats, /* domainBlockStats */
    testDomainInterfaceStats, /* domainInterfaceStats */
5409
    NULL, /* domainMemoryStats */
R
Richard W.M. Jones 已提交
5410
    NULL, /* domainBlockPeek */
R
Richard W.M. Jones 已提交
5411
    NULL, /* domainMemoryPeek */
5412
    NULL, /* domainGetBlockInfo */
5413
    testNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
5414
    NULL, /* getFreeMemory */
5415 5416
    testDomainEventRegister, /* domainEventRegister */
    testDomainEventDeregister, /* domainEventDeregister */
D
Daniel Veillard 已提交
5417 5418
    NULL, /* domainMigratePrepare2 */
    NULL, /* domainMigrateFinish2 */
5419
    NULL, /* nodeDeviceDettach */
5420 5421
    NULL, /* nodeDeviceReAttach */
    NULL, /* nodeDeviceReset */
C
Chris Lalancette 已提交
5422
    NULL, /* domainMigratePrepareTunnel */
5423 5424 5425 5426
    testIsEncrypted, /* isEncrypted */
    testIsSecure, /* isEncrypted */
    testDomainIsActive, /* domainIsActive */
    testDomainIsPersistent, /* domainIsPersistent */
5427
    testDomainIsUpdated, /* domainIsUpdated */
J
Jiri Denemark 已提交
5428
    NULL, /* cpuCompare */
5429
    NULL, /* cpuBaseline */
5430
    NULL, /* domainGetJobInfo */
5431
    NULL, /* domainAbortJob */
5432
    NULL, /* domainMigrateSetMaxDowntime */
5433
    NULL, /* domainMigrateSetMaxSpeed */
5434 5435
    testDomainEventRegisterAny, /* domainEventRegisterAny */
    testDomainEventDeregisterAny, /* domainEventDeregisterAny */
5436 5437 5438
    NULL, /* domainManagedSave */
    NULL, /* domainHasManagedSaveImage */
    NULL, /* domainManagedSaveRemove */
C
Chris Lalancette 已提交
5439 5440 5441 5442 5443 5444 5445 5446 5447
    NULL, /* domainSnapshotCreateXML */
    NULL, /* domainSnapshotDumpXML */
    NULL, /* domainSnapshotNum */
    NULL, /* domainSnapshotListNames */
    NULL, /* domainSnapshotLookupByName */
    NULL, /* domainHasCurrentSnapshot */
    NULL, /* domainSnapshotCurrent */
    NULL, /* domainRevertToSnapshot */
    NULL, /* domainSnapshotDelete */
C
Chris Lalancette 已提交
5448
    NULL, /* qemuDomainMonitorCommand */
5449
    NULL, /* domainOpenConsole */
5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470
};

static virNetworkDriver testNetworkDriver = {
    "Test",
    testOpenNetwork, /* open */
    testCloseNetwork, /* close */
    testNumNetworks, /* numOfNetworks */
    testListNetworks, /* listNetworks */
    testNumDefinedNetworks, /* numOfDefinedNetworks */
    testListDefinedNetworks, /* listDefinedNetworks */
    testLookupNetworkByUUID, /* networkLookupByUUID */
    testLookupNetworkByName, /* networkLookupByName */
    testNetworkCreate, /* networkCreateXML */
    testNetworkDefine, /* networkDefineXML */
    testNetworkUndefine, /* networkUndefine */
    testNetworkStart, /* networkCreate */
    testNetworkDestroy, /* networkDestroy */
    testNetworkDumpXML, /* networkDumpXML */
    testNetworkGetBridgeName, /* networkGetBridgeName */
    testNetworkGetAutostart, /* networkGetAutostart */
    testNetworkSetAutostart, /* networkSetAutostart */
5471 5472
    testNetworkIsActive, /* networkIsActive */
    testNetworkIsPersistent, /* networkIsPersistent */
5473 5474
};

L
Laine Stump 已提交
5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489
static virInterfaceDriver testInterfaceDriver = {
    "Test",                     /* name */
    testOpenInterface,          /* open */
    testCloseInterface,         /* close */
    testNumOfInterfaces,        /* numOfInterfaces */
    testListInterfaces,         /* listInterfaces */
    testNumOfDefinedInterfaces, /* numOfDefinedInterfaces */
    testListDefinedInterfaces,  /* listDefinedInterfaces */
    testLookupInterfaceByName,  /* interfaceLookupByName */
    testLookupInterfaceByMACString, /* interfaceLookupByMACString */
    testInterfaceGetXMLDesc,    /* interfaceGetXMLDesc */
    testInterfaceDefineXML,     /* interfaceDefineXML */
    testInterfaceUndefine,      /* interfaceUndefine */
    testInterfaceCreate,        /* interfaceCreate */
    testInterfaceDestroy,       /* interfaceDestroy */
5490
    testInterfaceIsActive,      /* interfaceIsActive */
L
Laine Stump 已提交
5491 5492 5493
};


5494 5495 5496 5497
static virStorageDriver testStorageDriver = {
    .name = "Test",
    .open = testStorageOpen,
    .close = testStorageClose,
C
Cole Robinson 已提交
5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525

    .numOfPools = testStorageNumPools,
    .listPools = testStorageListPools,
    .numOfDefinedPools = testStorageNumDefinedPools,
    .listDefinedPools = testStorageListDefinedPools,
    .findPoolSources = testStorageFindPoolSources,
    .poolLookupByName = testStoragePoolLookupByName,
    .poolLookupByUUID = testStoragePoolLookupByUUID,
    .poolLookupByVolume = testStoragePoolLookupByVolume,
    .poolCreateXML = testStoragePoolCreate,
    .poolDefineXML = testStoragePoolDefine,
    .poolBuild = testStoragePoolBuild,
    .poolUndefine = testStoragePoolUndefine,
    .poolCreate = testStoragePoolStart,
    .poolDestroy = testStoragePoolDestroy,
    .poolDelete = testStoragePoolDelete,
    .poolRefresh = testStoragePoolRefresh,
    .poolGetInfo = testStoragePoolGetInfo,
    .poolGetXMLDesc = testStoragePoolDumpXML,
    .poolGetAutostart = testStoragePoolGetAutostart,
    .poolSetAutostart = testStoragePoolSetAutostart,
    .poolNumOfVolumes = testStoragePoolNumVolumes,
    .poolListVolumes = testStoragePoolListVolumes,

    .volLookupByName = testStorageVolumeLookupByName,
    .volLookupByKey = testStorageVolumeLookupByKey,
    .volLookupByPath = testStorageVolumeLookupByPath,
    .volCreateXML = testStorageVolumeCreateXML,
5526
    .volCreateXMLFrom = testStorageVolumeCreateXMLFrom,
C
Cole Robinson 已提交
5527 5528 5529 5530
    .volDelete = testStorageVolumeDelete,
    .volGetInfo = testStorageVolumeGetInfo,
    .volGetXMLDesc = testStorageVolumeGetXMLDesc,
    .volGetPath = testStorageVolumeGetPath,
5531 5532
    .poolIsActive = testStoragePoolIsActive,
    .poolIsPersistent = testStoragePoolIsPersistent,
5533 5534
};

5535 5536 5537 5538
static virDeviceMonitor testDevMonitor = {
    .name = "Test",
    .open = testDevMonOpen,
    .close = testDevMonClose,
5539 5540 5541 5542 5543 5544 5545 5546

    .numOfDevices = testNodeNumOfDevices,
    .listDevices = testNodeListDevices,
    .deviceLookupByName = testNodeDeviceLookupByName,
    .deviceDumpXML = testNodeDeviceDumpXML,
    .deviceGetParent = testNodeDeviceGetParent,
    .deviceNumOfCaps = testNodeDeviceNumOfCaps,
    .deviceListCaps = testNodeDeviceListCaps,
5547 5548
    .deviceCreateXML = testNodeDeviceCreateXML,
    .deviceDestroy = testNodeDeviceDestroy,
5549 5550
};

5551 5552 5553 5554 5555
static virSecretDriver testSecretDriver = {
    .name = "Test",
    .open = testSecretOpen,
    .close = testSecretClose,
};
5556 5557


5558 5559 5560 5561 5562 5563
static virNWFilterDriver testNWFilterDriver = {
    .name = "Test",
    .open = testNWFilterOpen,
    .close = testNWFilterClose,
};

5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
    if (virRegisterDriver(&testDriver) < 0)
        return -1;
    if (virRegisterNetworkDriver(&testNetworkDriver) < 0)
        return -1;
L
Laine Stump 已提交
5576 5577
    if (virRegisterInterfaceDriver(&testInterfaceDriver) < 0)
        return -1;
5578 5579
    if (virRegisterStorageDriver(&testStorageDriver) < 0)
        return -1;
5580 5581
    if (virRegisterDeviceMonitor(&testDevMonitor) < 0)
        return -1;
5582 5583
    if (virRegisterSecretDriver(&testSecretDriver) < 0)
        return -1;
5584 5585
    if (virRegisterNWFilterDriver(&testNWFilterDriver) < 0)
        return -1;
5586

5587 5588
    return 0;
}