test.c 45.4 KB
Newer Older
1 2 3
/*
 * test.c: A "mock" hypervisor for use by application unit tests
 *
4
 * Copyright (C) 2006-2008 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 32
#include <sys/stat.h>

33
#include "test.h"
34
#include "buf.h"
35
#include "util.h"
36
#include "uuid.h"
37
#include "capabilities.h"
38
#include "memory.h"
39
#include "network_conf.h"
40 41
#include "domain_conf.h"
#include "xml.h"
42

43 44 45 46 47 48 49 50 51 52 53
#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
54

55 56 57
struct _testConn {
    char path[PATH_MAX];
    int nextDomID;
58
    virCapsPtr caps;
59
    virNodeInfo nodeInfo;
60
    virDomainObjList domains;
61
    virNetworkObjList networks;
62 63
    int numCells;
    testCell cells[MAX_CELLS];
64 65 66
};
typedef struct _testConn testConn;
typedef struct _testConn *testConnPtr;
67

68
#define TEST_MODEL "i686"
69
#define TEST_MODEL_WORDSIZE 32
70
#define TEST_EMULATOR "/usr/bin/test-hv"
71

72
static const virNodeInfo defaultNodeInfo = {
73
    TEST_MODEL,
74 75 76 77 78 79 80
    1024*1024*3, /* 3 GB */
    16,
    1400,
    2,
    2,
    2,
    2,
81 82
};

83 84
#define GET_DOMAIN(dom, ret)                                            \
    testConnPtr privconn;                                               \
85
    virDomainObjPtr privdom;                                            \
86 87
                                                                        \
    privconn = (testConnPtr)dom->conn->privateData;                     \
88
    do {                                                                \
89 90 91
        if ((privdom = virDomainFindByName(&privconn->domains,           \
                                            (dom)->name)) == NULL) {    \
            testError((dom)->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);  \
92 93 94
            return (ret);                                               \
        }                                                               \
    } while (0)
95 96 97

#define GET_NETWORK(net, ret)                                           \
    testConnPtr privconn;                                               \
98
    virNetworkObjPtr privnet;                                           \
99 100
                                                                        \
    privconn = (testConnPtr)net->conn->privateData;                     \
101
    do {                                                                \
102
        if ((privnet = virNetworkFindByName(&privconn->networks,        \
103
                                            (net)->name)) == NULL) {    \
104
            testError((net)->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);  \
105 106 107
            return (ret);                                               \
        }                                                               \
    } while (0)
108

109
#define GET_CONNECTION(conn)                                            \
110 111 112 113 114
    testConnPtr privconn;                                               \
                                                                        \
    privconn = (testConnPtr)conn->privateData;


115 116
#define testError(conn, code, fmt...)                               \
        __virReportErrorHelper(conn, VIR_FROM_TEST, code, __FILE__, \
117
                               __FUNCTION__, __LINE__, fmt)
118

119 120 121 122 123 124 125
static virCapsPtr
testBuildCapabilities(virConnectPtr conn) {
    virCapsPtr caps;
    virCapsGuestPtr guest;
    const char *const guest_types[] = { "hvm", "xen" };
    int i;
    GET_CONNECTION(conn);
126

127 128
    if ((caps = virCapabilitiesNew(TEST_MODEL, 0, 0)) == NULL)
        goto no_memory;
129

130 131 132 133
    if (virCapabilitiesAddHostFeature(caps, "pae") < 0)
        goto no_memory;
    if (virCapabilitiesAddHostFeature(caps ,"nonpae") < 0)
        goto no_memory;
134

135 136 137 138
    for (i = 0; i < privconn->numCells; i++) {
        if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].numCpus,
                                           privconn->cells[i].cpus) < 0)
            goto no_memory;
139 140
    }

141 142 143 144 145 146 147 148 149 150
    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;
151

152 153 154 155 156 157 158
        if (virCapabilitiesAddGuestDomain(guest,
                                          "test",
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
            goto no_memory;
159

160 161 162 163
        if (virCapabilitiesAddGuestFeature(guest, "pae", 1, 1) == NULL)
            goto no_memory;
        if (virCapabilitiesAddGuestFeature(guest ,"nonpae", 1, 1) == NULL)
            goto no_memory;
164 165
    }

166
    return caps;
167

168
no_memory:
169
    testError(conn, VIR_ERR_NO_MEMORY, NULL);
170 171
    virCapabilitiesFree(caps);
    return NULL;
172 173
}

174

175 176 177 178 179 180 181 182 183 184
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>";
185 186


187 188 189 190 191 192 193 194 195 196 197
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>";
198 199


200
static int testOpenDefault(virConnectPtr conn) {
201 202
    int u;
    struct timeval tv;
203
    testConnPtr privconn;
204 205 206 207
    virDomainDefPtr domdef = NULL;
    virDomainObjPtr domobj = NULL;
    virNetworkDefPtr netdef = NULL;
    virNetworkObjPtr netobj = NULL;
208

209
    if (VIR_ALLOC(privconn) < 0) {
210
        testError(conn, VIR_ERR_NO_MEMORY, "testConn");
211 212
        return VIR_DRV_OPEN_ERROR;
    }
213
    conn->privateData = privconn;
214 215

    if (gettimeofday(&tv, NULL) < 0) {
J
Jim Meyering 已提交
216
        testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("getting time of day"));
217
        goto error;
218 219
    }

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

222 223 224 225 226 227 228 229 230 231
    // Numa setup
    privconn->numCells = 2;
    for (u = 0; u < 2; ++u) {
        privconn->cells[u].numCpus = 8;
        privconn->cells[u].mem = (u + 1) * 2048 * 1024;
    }
    for (u = 0 ; u < 16 ; u++) {
        privconn->cells[u % 2].cpus[(u / 2)] = u;
    }

232 233 234 235 236 237 238 239 240 241 242
    if (!(privconn->caps = testBuildCapabilities(conn)))
        goto error;

    privconn->nextDomID = 1;

    if (!(domdef = virDomainDefParseString(conn, privconn->caps, defaultDomainXML)))
        goto error;
    if (!(domobj = virDomainAssignDef(conn, &privconn->domains, domdef))) {
        virDomainDefFree(domdef);
        goto error;
    }
243
    domobj->def->id = privconn->nextDomID++;
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
    domobj->state = VIR_DOMAIN_RUNNING;
    domobj->persistent = 1;

    if (!(netdef = virNetworkDefParseString(conn, defaultNetworkXML)))
        goto error;
    if (!(netobj = virNetworkAssignDef(conn, &privconn->networks, netdef))) {
        virNetworkDefFree(netdef);
        goto error;
    }

    netobj->active = 1;
    netobj->persistent = 1;

    return VIR_DRV_OPEN_SUCCESS;

error:
260
    virDomainObjListFree(&privconn->domains);
261
    virNetworkObjListFree(&privconn->networks);
262 263 264
    virCapabilitiesFree(privconn->caps);
    VIR_FREE(privconn);
    return VIR_DRV_OPEN_ERROR;
265 266 267 268
}


static char *testBuildFilename(const char *relativeTo,
269 270 271 272 273 274 275 276
                               const char *filename) {
    char *offset;
    int baseLen;
    if (!filename || filename[0] == '\0')
        return (NULL);
    if (filename[0] == '/')
        return strdup(filename);

277
    offset = strrchr(relativeTo, '/');
278
    if ((baseLen = (offset-relativeTo+1))) {
279 280 281
        char *absFile;
        if (VIR_ALLOC_N(absFile, baseLen + strlen(filename) + 1) < 0)
            return NULL;
282 283 284 285 286 287 288
        strncpy(absFile, relativeTo, baseLen);
        absFile[baseLen] = '\0';
        strcat(absFile, filename);
        return absFile;
    } else {
        return strdup(filename);
    }
289 290 291
}

static int testOpenFromFile(virConnectPtr conn,
292
                            const char *file) {
293
    int fd = -1, i, ret;
294 295
    long l;
    char *str;
296
    xmlDocPtr xml = NULL;
297
    xmlNodePtr root = NULL;
D
Daniel P. Berrange 已提交
298
    xmlNodePtr *domains = NULL, *networks = NULL;
299 300
    xmlXPathContextPtr ctxt = NULL;
    virNodeInfoPtr nodeInfo;
301 302
    virNetworkObjPtr net;
    virDomainObjPtr dom;
303 304
    testConnPtr privconn;
    if (VIR_ALLOC(privconn) < 0) {
305
        testError(NULL, VIR_ERR_NO_MEMORY, "testConn");
306 307
        return VIR_DRV_OPEN_ERROR;
    }
308 309 310 311
    conn->privateData = privconn;

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

    if ((fd = open(file, O_RDONLY)) < 0) {
J
Jim Meyering 已提交
314
        testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("loading host definition file"));
315
        goto error;
316 317
    }

318 319 320
    if (!(xml = xmlReadFd(fd, file, NULL,
                          XML_PARSE_NOENT | XML_PARSE_NONET |
                          XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
J
Jim Meyering 已提交
321
        testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("host"));
322
        goto error;
323
    }
324 325
    close(fd);
    fd = -1;
326

327 328
    root = xmlDocGetRootElement(xml);
    if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "node"))) {
J
Jim Meyering 已提交
329
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node"));
330
        goto error;
331 332
    }

333 334
    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
J
Jim Meyering 已提交
335
        testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("creating xpath context"));
336
        goto error;
337
    }
338

339
    privconn->nextDomID = 1;
340
    privconn->numCells = 0;
341 342 343 344 345
    strncpy(privconn->path, file, PATH_MAX-1);
    privconn->path[PATH_MAX-1] = '\0';
    memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));

    nodeInfo = &privconn->nodeInfo;
346
    ret = virXPathLong(conn, "string(/node/cpu/nodes[1])", ctxt, &l);
347 348 349
    if (ret == 0) {
        nodeInfo->nodes = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
350
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu numa nodes"));
351
        goto error;
352
    }
353

354
    ret = virXPathLong(conn, "string(/node/cpu/sockets[1])", ctxt, &l);
355 356 357
    if (ret == 0) {
        nodeInfo->sockets = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
358
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu sockets"));
359
        goto error;
360
    }
361

362
    ret = virXPathLong(conn, "string(/node/cpu/cores[1])", ctxt, &l);
363 364 365
    if (ret == 0) {
        nodeInfo->cores = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
366
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu cores"));
367
        goto error;
368 369
    }

370
    ret = virXPathLong(conn, "string(/node/cpu/threads[1])", ctxt, &l);
371 372 373
    if (ret == 0) {
        nodeInfo->threads = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
374
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu threads"));
375
        goto error;
376
    }
377

378
    nodeInfo->cpus = nodeInfo->cores * nodeInfo->threads * nodeInfo->sockets * nodeInfo->nodes;
379
    ret = virXPathLong(conn, "string(/node/cpu/active[1])", ctxt, &l);
380 381
    if (ret == 0) {
        if (l < nodeInfo->cpus) {
382 383
            nodeInfo->cpus = l;
        }
384
    } else if (ret == -2) {
J
Jim Meyering 已提交
385
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node active cpu"));
386
        goto error;
387
    }
388
    ret = virXPathLong(conn, "string(/node/cpu/mhz[1])", ctxt, &l);
389 390 391
    if (ret == 0) {
        nodeInfo->mhz = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
392
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node cpu mhz"));
393
        goto error;
394 395
    }

396
    str = virXPathString(conn, "string(/node/cpu/model[1])", ctxt);
397 398
    if (str != NULL) {
        strncpy(nodeInfo->model, str, sizeof(nodeInfo->model)-1);
399
        nodeInfo->model[sizeof(nodeInfo->model)-1] = '\0';
400
        VIR_FREE(str);
401 402
    }

403
    ret = virXPathLong(conn, "string(/node/memory[1])", ctxt, &l);
404 405 406
    if (ret == 0) {
        nodeInfo->memory = l;
    } else if (ret == -2) {
J
Jim Meyering 已提交
407
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node memory"));
408
        goto error;
409
    }
410

411
    ret = virXPathNodeSet(conn, "/node/domain", ctxt, &domains);
412
    if (ret < 0) {
J
Jim Meyering 已提交
413
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node domain list"));
414
        goto error;
415
    }
416

417
    for (i = 0 ; i < ret ; i++) {
418 419 420 421 422 423
        virDomainDefPtr def;
        char *relFile = virXMLPropString(domains[i], "file");
        if (relFile != NULL) {
            char *absFile = testBuildFilename(file, relFile);
            VIR_FREE(relFile);
            if (!absFile) {
J
Jim Meyering 已提交
424
                testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("resolving domain filename"));
425 426 427
                goto error;
            }
            def = virDomainDefParseFile(conn, privconn->caps, absFile);
428
            VIR_FREE(absFile);
429 430 431 432 433 434 435 436 437
            if (!def)
                goto error;
        } else {
            if ((def = virDomainDefParseNode(conn, privconn->caps, xml, domains[i])) == NULL)
                goto error;
        }

        if (!(dom = virDomainAssignDef(conn, &privconn->domains, def))) {
            virDomainDefFree(def);
438 439
            goto error;
        }
440 441 442 443

        dom->state = VIR_DOMAIN_RUNNING;
        dom->def->id = privconn->nextDomID++;
        dom->persistent = 1;
444
    }
445
    if (domains != NULL)
446
        VIR_FREE(domains);
447

448
    ret = virXPathNodeSet(conn, "/node/network", ctxt, &networks);
449
    if (ret < 0) {
J
Jim Meyering 已提交
450
        testError(NULL, VIR_ERR_XML_ERROR, "%s", _("node network list"));
451 452 453 454 455 456 457 458
        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);
459
            if (!absFile) {
J
Jim Meyering 已提交
460
                testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("resolving network filename"));
461 462
                goto error;
            }
463 464

            def = virNetworkDefParseFile(conn, absFile);
465
            VIR_FREE(absFile);
466 467 468 469 470
            if (!def)
                goto error;
        } else {
            if ((def = virNetworkDefParseNode(conn, xml, networks[i])) == NULL)
                goto error;
471
        }
472 473 474 475
        if (!(net = virNetworkAssignDef(conn, &privconn->networks,
                                        def))) {
            virNetworkDefFree(def);
            goto error;
476
        }
477 478 479

        net->persistent = 1;
    }
480
    if (networks != NULL)
481
        VIR_FREE(networks);
482

J
Jim Meyering 已提交
483
    xmlXPathFreeContext(ctxt);
484
    xmlFreeDoc(xml);
485

486
    return (0);
487 488

 error:
J
Jim Meyering 已提交
489
    xmlXPathFreeContext(ctxt);
490
    xmlFreeDoc(xml);
491 492
    VIR_FREE(domains);
    VIR_FREE(networks);
493 494
    if (fd != -1)
        close(fd);
495
    virDomainObjListFree(&privconn->domains);
496
    virNetworkObjListFree(&privconn->networks);
497
    VIR_FREE(privconn);
498
    conn->privateData = NULL;
499
    return VIR_DRV_OPEN_ERROR;
500 501
}

502

503
static int testOpen(virConnectPtr conn,
504
                    xmlURIPtr uri,
505
                    virConnectAuthPtr auth ATTRIBUTE_UNUSED,
506
                    int flags ATTRIBUTE_UNUSED)
507
{
508
    int ret;
509

510
    if (!uri)
511
        return VIR_DRV_OPEN_DECLINED;
512

513
    if (!uri->scheme || STRNEQ(uri->scheme, "test"))
514
        return VIR_DRV_OPEN_DECLINED;
515

516
    /* Remote driver should handle these. */
517
    if (uri->server)
518 519
        return VIR_DRV_OPEN_DECLINED;

520
    if (uri->server)
521 522
        return VIR_DRV_OPEN_DECLINED;

523 524 525 526
    /* From this point on, the connection is for us. */
    if (!uri->path
        || uri->path[0] == '\0'
        || (uri->path[0] == '/' && uri->path[1] == '\0')) {
527
        testError (NULL, VIR_ERR_INVALID_ARG,
J
Jim Meyering 已提交
528
                   "%s", _("testOpen: supply a path or use test:///default"));
529 530
        return VIR_DRV_OPEN_ERROR;
    }
531

532 533 534
    if (STREQ(uri->path, "/default"))
        ret = testOpenDefault(conn);
    else
535 536 537 538
        ret = testOpenFromFile(conn,
                               uri->path);

    return (ret);
539 540
}

541
static int testClose(virConnectPtr conn)
542
{
543
    GET_CONNECTION(conn);
544

545
    virCapabilitiesFree(privconn->caps);
546
    virDomainObjListFree(&privconn->domains);
547 548
    virNetworkObjListFree(&privconn->networks);

549
    VIR_FREE (privconn);
550
    conn->privateData = conn;
551
    return 0;
552 553
}

554 555
static int testGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED,
                          unsigned long *hvVer)
556
{
557 558
    *hvVer = 2;
    return (0);
559 560
}

561
static char *testGetHostname (virConnectPtr conn)
562 563 564 565 566 567
{
    int r;
    char hostname [HOST_NAME_MAX+1], *str;

    r = gethostname (hostname, HOST_NAME_MAX+1);
    if (r == -1) {
568
        testError (conn, VIR_ERR_SYSTEM_ERROR, "%s",
569
                   strerror (errno));
570 571 572 573
        return NULL;
    }
    str = strdup (hostname);
    if (str == NULL) {
574
        testError (conn, VIR_ERR_SYSTEM_ERROR, "%s",
575
                   strerror (errno));
576 577 578 579 580
        return NULL;
    }
    return str;
}

581
static char * testGetURI (virConnectPtr conn)
582 583
{
    char *uri;
584
    GET_CONNECTION(conn);
585

586
    if (asprintf (&uri, "test://%s", privconn->path) == -1) {
587
        testError (conn, VIR_ERR_SYSTEM_ERROR, "%s",
588
                   strerror (errno));
589 590 591 592 593
        return NULL;
    }
    return uri;
}

594 595 596 597 598 599 600 601
static int testGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED,
                           const char *type ATTRIBUTE_UNUSED)
{
    return 32;
}

static int testNodeGetInfo(virConnectPtr conn,
                           virNodeInfoPtr info)
602
{
603
    GET_CONNECTION(conn);
604
    memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo));
605
    return (0);
606 607
}

608
static char *testGetCapabilities (virConnectPtr conn)
609
{
610
    char *xml;
611
    GET_CONNECTION(conn);
612

613
    if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL) {
614
        testError(conn, VIR_ERR_NO_MEMORY, NULL);
615
        return NULL;
616
    }
617 618

    return xml;
619 620
}

621
static int testNumOfDomains(virConnectPtr conn)
622
{
623
    unsigned int numActive = 0, i;
624
    GET_CONNECTION(conn);
625

626 627
    for (i = 0 ; i < privconn->domains.count ; i++)
        if (virDomainIsActive(privconn->domains.objs[i]))
628
            numActive++;
629

630
    return numActive;
631 632
}

633
static virDomainPtr
634
testDomainCreateXML(virConnectPtr conn, const char *xml,
635
                      unsigned int flags ATTRIBUTE_UNUSED)
636
{
637 638 639 640
    virDomainPtr ret;
    virDomainDefPtr def;
    virDomainObjPtr dom;
    GET_CONNECTION(conn);
641

642 643
    if ((def = virDomainDefParseString(conn, privconn->caps, xml)) == NULL)
        return NULL;
644

645 646 647 648
    if ((dom = virDomainAssignDef(conn, &privconn->domains,
                                  def)) == NULL) {
        virDomainDefFree(def);
        return NULL;
649
    }
650 651
    dom->state = VIR_DOMAIN_RUNNING;
    dom->def->id = privconn->nextDomID++;
652

653 654 655 656 657
    ret = virGetDomain(conn, def->name, def->uuid);
    if (!ret)
        return NULL;
    ret->id = def->id;
    return ret;
658 659 660
}


661 662
static virDomainPtr testLookupDomainByID(virConnectPtr conn,
                                         int id)
663
{
664 665 666
    virDomainObjPtr dom = NULL;
    virDomainPtr ret;
    GET_CONNECTION(conn);
667

668
    if ((dom = virDomainFindByID(&privconn->domains, id)) == NULL) {
669
        testError (conn, VIR_ERR_NO_DOMAIN, NULL);
670
        return NULL;
671 672
    }

673 674 675 676 677
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
    if (!ret)
        return NULL;
    ret->id = dom->def->id;
    return ret;
678 679
}

680 681
static virDomainPtr testLookupDomainByUUID(virConnectPtr conn,
                                           const unsigned char *uuid)
682
{
683 684 685
    virDomainPtr ret;
    virDomainObjPtr dom = NULL;
    GET_CONNECTION(conn);
686

687
    if ((dom = virDomainFindByUUID(&privconn->domains, uuid)) == NULL) {
688
        testError (conn, VIR_ERR_NO_DOMAIN, NULL);
689
        return NULL;
690
    }
691

692 693 694 695 696
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
    if (!ret)
        return NULL;
    ret->id = dom->def->id;
    return ret;
697 698
}

699 700
static virDomainPtr testLookupDomainByName(virConnectPtr conn,
                                           const char *name)
701
{
702 703 704
    virDomainPtr ret;
    virDomainObjPtr dom = NULL;
    GET_CONNECTION(conn);
705

706
    if ((dom = virDomainFindByName(&privconn->domains, name)) == NULL) {
707
        testError (conn, VIR_ERR_NO_DOMAIN, NULL);
708
        return NULL;
709
    }
710

711 712 713 714 715
    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
    if (!ret)
        return NULL;
    ret->id = dom->def->id;
    return ret;
716 717
}

718 719 720
static int testListDomains (virConnectPtr conn,
                            int *ids,
                            int maxids)
721
{
722
    unsigned int n = 0, i;
723
    GET_CONNECTION(conn);
724

725 726 727 728
    for (i = 0 ; i < privconn->domains.count && n < maxids ; i++)
        if (virDomainIsActive(privconn->domains.objs[i]))
            ids[n++] = privconn->domains.objs[i]->def->id;

729
    return n;
730 731
}

732
static int testDestroyDomain (virDomainPtr domain)
733
{
734
    GET_DOMAIN(domain, -1);
735

736
    privdom->state = VIR_DOMAIN_SHUTOFF;
737 738
    privdom->def->id = -1;
    domain->id = -1;
739 740 741
    if (!privdom->persistent) {
        virDomainRemoveInactive(&privconn->domains,
                                privdom);
742
    }
743
    return (0);
744 745
}

746
static int testResumeDomain (virDomainPtr domain)
747
{
748
    GET_DOMAIN(domain, -1);
749

750
    if (privdom->state != VIR_DOMAIN_PAUSED) {
751 752 753
        testError(domain->conn,
                  VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"),
                  domain->name);
754 755
        return -1;
    }
756

757
    privdom->state = VIR_DOMAIN_RUNNING;
758
    return (0);
759 760
}

761
static int testPauseDomain (virDomainPtr domain)
762
{
763
    GET_DOMAIN(domain, -1);
764

765 766
    if (privdom->state == VIR_DOMAIN_SHUTOFF ||
        privdom->state == VIR_DOMAIN_PAUSED) {
767 768 769
        testError(domain->conn,
                  VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"),
                  domain->name);
770 771
        return -1;
    }
772

773
    privdom->state = VIR_DOMAIN_PAUSED;
774
    return (0);
775 776
}

777
static int testShutdownDomain (virDomainPtr domain)
778
{
779
    GET_DOMAIN(domain, -1);
780

781
    if (privdom->state == VIR_DOMAIN_SHUTOFF) {
782 783
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("domain '%s' not running"), domain->name);
784
        return -1;
785
    }
786

787
    privdom->state = VIR_DOMAIN_SHUTOFF;
788
    domain->id = -1;
789
    privdom->def->id = -1;
790 791

    return (0);
792 793 794
}

/* Similar behaviour as shutdown */
795 796
static int testRebootDomain (virDomainPtr domain,
                             unsigned int action ATTRIBUTE_UNUSED)
797
{
798
    GET_DOMAIN(domain, -1);
799

800 801 802 803
    privdom->state = VIR_DOMAIN_SHUTDOWN;
    switch (privdom->def->onReboot) {
    case VIR_DOMAIN_LIFECYCLE_DESTROY:
        privdom->state = VIR_DOMAIN_SHUTOFF;
804
        domain->id = -1;
805
        privdom->def->id = -1;
806 807
        break;

808 809
    case VIR_DOMAIN_LIFECYCLE_RESTART:
        privdom->state = VIR_DOMAIN_RUNNING;
810 811
        break;

812 813
    case VIR_DOMAIN_LIFECYCLE_PRESERVE:
        privdom->state = VIR_DOMAIN_SHUTOFF;
814
        domain->id = -1;
815
        privdom->def->id = -1;
816 817
        break;

818 819
    case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME:
        privdom->state = VIR_DOMAIN_RUNNING;
820
        break;
821

822
    default:
823
        privdom->state = VIR_DOMAIN_SHUTOFF;
824
        domain->id = -1;
825
        privdom->def->id = -1;
826 827
        break;
    }
828

829
    return (0);
830 831
}

832 833
static int testGetDomainInfo (virDomainPtr domain,
                              virDomainInfoPtr info)
834
{
835
    struct timeval tv;
836
    GET_DOMAIN(domain, -1);
837 838

    if (gettimeofday(&tv, NULL) < 0) {
839
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
840
                  "%s", _("getting time of day"));
841 842 843
        return (-1);
    }

844 845 846 847 848
    info->state = privdom->state;
    info->memory = privdom->def->memory;
    info->maxMem = privdom->def->maxmem;
    info->nrVirtCpu = privdom->def->vcpus;
    info->cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
849
    return (0);
850 851
}

852
static char *testDomainDumpXML(virDomainPtr domain, int flags);
853

854 855 856 857 858 859 860 861
#define TEST_SAVE_MAGIC "TestGuestMagic"

static int testDomainSave(virDomainPtr domain,
                          const char *path)
{
    char *xml;
    int fd, len;
    GET_DOMAIN(domain, -1);
862

863
    xml = testDomainDumpXML(domain, 0);
864
    if (xml == NULL) {
865 866 867
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("saving domain '%s' failed to allocate space for metadata: %s"),
                  domain->name, strerror(errno));
868 869
        return (-1);
    }
870 871

    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
872 873 874
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("saving domain '%s' to '%s': open failed: %s"),
                  domain->name, path, strerror(errno));
875 876
        return (-1);
    }
877
    len = strlen(xml);
878
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
879 880 881
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("saving domain '%s' to '%s': write failed: %s"),
                  domain->name, path, strerror(errno));
882 883 884
        close(fd);
        return (-1);
    }
885
    if (safewrite(fd, (char*)&len, sizeof(len)) < 0) {
886 887 888
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("saving domain '%s' to '%s': write failed: %s"),
                  domain->name, path, strerror(errno));
889 890 891
        close(fd);
        return (-1);
    }
892
    if (safewrite(fd, xml, len) < 0) {
893 894 895
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("saving domain '%s' to '%s': write failed: %s"),
                  domain->name, path, strerror(errno));
896
        VIR_FREE(xml);
897 898 899
        close(fd);
        return (-1);
    }
900
    VIR_FREE(xml);
901
    if (close(fd) < 0) {
902 903 904
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("saving domain '%s' to '%s': write failed: %s"),
                  domain->name, path, strerror(errno));
905 906 907
        close(fd);
        return (-1);
    }
908 909 910 911
    privdom->state = VIR_DOMAIN_SHUTOFF;
    if (!privdom->persistent) {
        virDomainRemoveInactive(&privconn->domains,
                                privdom);
912 913
    }
    return 0;
914 915
}

916 917
static int testDomainRestore(virConnectPtr conn,
                             const char *path)
918
{
919 920
    char *xml;
    char magic[15];
921 922 923 924
    int fd, len;
    virDomainDefPtr def;
    virDomainObjPtr dom;
    GET_CONNECTION(conn);
925 926

    if ((fd = open(path, O_RDONLY)) < 0) {
927
        testError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
928
                  "%s", _("cannot read domain image"));
929 930
        return (-1);
    }
931
    if (read(fd, magic, sizeof(magic)) != sizeof(magic)) {
932
        testError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
933
                  "%s", _("incomplete save header"));
934
        close(fd);
935 936
        return (-1);
    }
937
    if (memcmp(magic, TEST_SAVE_MAGIC, sizeof(magic))) {
938
        testError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
939
                  "%s", _("mismatched header magic"));
940 941 942 943
        close(fd);
        return (-1);
    }
    if (read(fd, (char*)&len, sizeof(len)) != sizeof(len)) {
944
        testError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
945
                  "%s", _("failed to read metadata length"));
946 947 948 949
        close(fd);
        return (-1);
    }
    if (len < 1 || len > 8192) {
950
        testError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
951
                  "%s", _("length of metadata out of range"));
952 953 954
        close(fd);
        return (-1);
    }
955
    if (VIR_ALLOC_N(xml, len+1) < 0) {
956
        testError(conn, VIR_ERR_NO_MEMORY, "xml");
957 958 959 960
        close(fd);
        return (-1);
    }
    if (read(fd, xml, len) != len) {
961
        testError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
962
                  "%s", _("incomplete metdata"));
963 964 965 966 967
        close(fd);
        return (-1);
    }
    xml[len] = '\0';
    close(fd);
968 969

    def = virDomainDefParseString(conn, privconn->caps, xml);
970
    VIR_FREE(xml);
971 972 973 974 975 976 977 978 979 980 981
    if (!def)
        return -1;

    if ((dom = virDomainAssignDef(conn, &privconn->domains,
                                  def)) == NULL) {
        virDomainDefFree(def);
        return -1;
    }
    dom->state = VIR_DOMAIN_RUNNING;
    dom->def->id = privconn->nextDomID++;
    return dom->def->id;
982 983
}

984 985 986
static int testDomainCoreDump(virDomainPtr domain,
                              const char *to,
                              int flags ATTRIBUTE_UNUSED)
987
{
988 989 990 991
    int fd;
    GET_DOMAIN(domain, -1);

    if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
992 993 994
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("domain '%s' coredump: failed to open %s: %s"),
                  domain->name, to, strerror (errno));
995 996
        return (-1);
    }
997
    if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
998 999 1000
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("domain '%s' coredump: failed to write header to %s: %s"),
                  domain->name, to, strerror (errno));
1001
        close(fd);
1002 1003
        return (-1);
    }
1004
    if (close(fd) < 0) {
1005 1006 1007
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("domain '%s' coredump: write failed: %s: %s"),
                  domain->name, to, strerror (errno));
1008
        close(fd);
1009 1010
        return (-1);
    }
1011 1012 1013 1014
    privdom->state = VIR_DOMAIN_SHUTOFF;
    if (!privdom->persistent) {
        virDomainRemoveInactive(&privconn->domains,
                                privdom);
1015 1016 1017 1018
    }
    return 0;
}

1019 1020 1021
static char *testGetOSType(virDomainPtr dom) {
    char *ret = strdup("linux");
    if (!ret)
1022
        testError(dom->conn, VIR_ERR_NO_MEMORY, NULL);
1023
    return ret;
1024 1025 1026 1027
}

static unsigned long testGetMaxMemory(virDomainPtr domain) {
    GET_DOMAIN(domain, -1);
1028

1029
    return privdom->def->maxmem;
1030 1031 1032 1033 1034 1035 1036 1037
}

static int testSetMaxMemory(virDomainPtr domain,
                            unsigned long memory)
{
    GET_DOMAIN(domain, -1);

    /* XXX validate not over host memory wrt to other domains */
1038
    privdom->def->maxmem = memory;
1039
    return (0);
1040 1041
}

1042 1043 1044 1045
static int testSetMemory(virDomainPtr domain,
                         unsigned long memory)
{
    GET_DOMAIN(domain, -1);
1046

1047
    if (memory > privdom->def->maxmem) {
1048
        testError(domain->conn,
1049
                  VIR_ERR_INVALID_ARG, __FUNCTION__);
1050 1051
        return (-1);
    }
1052

1053
    privdom->def->memory = memory;
1054 1055 1056 1057 1058 1059
    return (0);
}

static int testSetVcpus(virDomainPtr domain,
                        unsigned int nrCpus) {
    GET_DOMAIN(domain, -1);
1060

1061 1062
    /* We allow more cpus in guest than host */
    if (nrCpus > 32) {
1063
        testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
1064 1065
        return (-1);
    }
1066

1067
    privdom->def->vcpus = nrCpus;
1068
    return (0);
1069 1070
}

1071
static char *testDomainDumpXML(virDomainPtr domain, int flags)
1072
{
1073
    virDomainDefPtr def;
1074
    GET_DOMAIN(domain, NULL);
1075

1076 1077
    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;
1078

1079 1080 1081
    return virDomainDefFormat(domain->conn,
                              def,
                              flags);
1082
}
1083

1084
static int testNumOfDefinedDomains(virConnectPtr conn) {
1085
    unsigned int numInactive = 0, i;
1086
    GET_CONNECTION(conn);
1087

1088 1089
    for (i = 0 ; i < privconn->domains.count ; i++)
        if (!virDomainIsActive(privconn->domains.objs[i]))
1090
            numInactive++;
1091

1092
    return numInactive;
1093 1094
}

1095 1096 1097
static int testListDefinedDomains(virConnectPtr conn,
                                  char **const names,
                                  int maxnames) {
1098
    unsigned int n = 0, i;
1099 1100 1101
    GET_CONNECTION(conn);

    memset(names, 0, sizeof(*names)*maxnames);
1102 1103 1104
    for (i = 0 ; i < privconn->domains.count && n < maxnames ; i++)
        if (!virDomainIsActive(privconn->domains.objs[i]) &&
            !(names[n++] = strdup(privconn->domains.objs[i]->def->name)))
1105
            goto no_memory;
1106

1107 1108 1109
    return n;

no_memory:
1110
    testError(conn, VIR_ERR_NO_MEMORY, NULL);
1111 1112 1113
    for (n = 0 ; n < maxnames ; n++)
        VIR_FREE(names[n]);
    return -1;
1114 1115
}

1116
static virDomainPtr testDomainDefineXML(virConnectPtr conn,
1117 1118 1119 1120 1121
                                        const char *xml) {
    virDomainPtr ret;
    virDomainDefPtr def;
    virDomainObjPtr dom;
    GET_CONNECTION(conn);
1122

1123 1124
    if ((def = virDomainDefParseString(conn, privconn->caps, xml)) == NULL)
        return NULL;
1125

1126 1127 1128 1129 1130 1131 1132
    if ((dom = virDomainAssignDef(conn, &privconn->domains,
                                  def)) == NULL) {
        virDomainDefFree(def);
        return NULL;
    }
    dom->persistent = 1;
    dom->def->id = -1;
1133

1134 1135 1136 1137 1138
    ret = virGetDomain(conn, def->name, def->uuid);
    if (!ret)
        return NULL;
    ret->id = -1;
    return ret;
1139 1140
}

1141 1142 1143 1144 1145
static int testNodeGetCellsFreeMemory(virConnectPtr conn,
                                      unsigned long long *freemems,
                                      int startCell, int maxCells) {
    int i, j;

1146
    GET_CONNECTION(conn);
1147 1148

    if (startCell > privconn->numCells) {
1149
        testError(conn, VIR_ERR_INVALID_ARG,
J
Jim Meyering 已提交
1150
                  "%s", _("Range exceeds available cells"));
1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163
        return -1;
    }

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

    return j;
}


1164 1165
static int testDomainCreate(virDomainPtr domain) {
    GET_DOMAIN(domain, -1);
1166

1167
    if (privdom->state != VIR_DOMAIN_SHUTOFF) {
1168 1169
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Domain '%s' is already running"), domain->name);
1170 1171 1172
        return (-1);
    }

1173 1174
    domain->id = privdom->def->id = privconn->nextDomID++;
    privdom->state = VIR_DOMAIN_RUNNING;
1175

1176 1177 1178 1179 1180 1181
    return (0);
}

static int testDomainUndefine(virDomainPtr domain) {
    GET_DOMAIN(domain, -1);

1182
    if (privdom->state != VIR_DOMAIN_SHUTOFF) {
1183 1184
        testError(domain->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Domain '%s' is still running"), domain->name);
1185 1186 1187
        return (-1);
    }

1188 1189 1190
    privdom->state = VIR_DOMAIN_SHUTOFF;
    virDomainRemoveInactive(&privconn->domains,
                            privdom);
1191 1192 1193 1194

    return (0);
}

1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210
static int testDomainGetAutostart(virDomainPtr domain,
                                  int *autostart)
{
    GET_DOMAIN(domain, -1);
    *autostart = privdom->autostart;
    return (0);
}


static int testDomainSetAutostart(virDomainPtr domain,
                                  int autostart)
{
    GET_DOMAIN(domain, -1);
    privdom->autostart = autostart ? 1 : 0;
    return (0);
}
1211

1212 1213 1214 1215 1216 1217 1218
static char *testDomainGetSchedulerType(virDomainPtr domain,
                                        int *nparams)
{
    char *type;
    *nparams = 1;
    type = strdup("fair");
    if (!type) {
1219
        testError(domain->conn, VIR_ERR_NO_MEMORY, "schedular");
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230
        return (NULL);
    }
    return type;
}

static int testDomainGetSchedulerParams(virDomainPtr domain,
                                        virSchedParameterPtr params,
                                        int *nparams)
{
    GET_DOMAIN(domain, -1);
    if (*nparams != 1) {
1231
        testError(domain->conn, VIR_ERR_INVALID_ARG, "nparams");
1232 1233
        return (-1);
    }
1234 1235
    strcpy(params[0].field, "weight");
    params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT;
1236 1237 1238
    /* XXX */
    /*params[0].value.ui = privdom->weight;*/
    params[0].value.ui = 50;
1239 1240
    return 0;
}
1241 1242


1243 1244 1245 1246 1247 1248
static int testDomainSetSchedulerParams(virDomainPtr domain,
                                        virSchedParameterPtr params,
                                        int nparams)
{
    GET_DOMAIN(domain, -1);
    if (nparams != 1) {
1249
        testError(domain->conn, VIR_ERR_INVALID_ARG, "nparams");
1250 1251
        return (-1);
    }
1252
    if (STRNEQ(params[0].field, "weight")) {
1253
        testError(domain->conn, VIR_ERR_INVALID_ARG, "field");
1254 1255 1256
        return (-1);
    }
    if (params[0].type != VIR_DOMAIN_SCHED_FIELD_UINT) {
1257
        testError(domain->conn, VIR_ERR_INVALID_ARG, "type");
1258 1259
        return (-1);
    }
1260 1261
    /* XXX */
    /*privdom->weight = params[0].value.ui;*/
1262 1263 1264 1265
    return 0;
}

static virDrvOpenStatus testOpenNetwork(virConnectPtr conn,
1266
                                        xmlURIPtr uri ATTRIBUTE_UNUSED,
1267
                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284
                                        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)
{
1285
    virNetworkObjPtr net = NULL;
1286
    GET_CONNECTION(conn);
1287

1288
    if ((net = virNetworkFindByUUID(&privconn->networks, uuid)) == NULL) {
1289
        testError (conn, VIR_ERR_NO_NETWORK, NULL);
1290 1291 1292
        return NULL;
    }

1293
    return virGetNetwork(conn, net->def->name, net->def->uuid);
1294
}
1295

1296
static virNetworkPtr testLookupNetworkByName(virConnectPtr conn,
1297
                                             const char *name)
1298
{
1299
    virNetworkObjPtr net = NULL;
1300
    GET_CONNECTION(conn);
1301

1302
    if ((net = virNetworkFindByName(&privconn->networks, name)) == NULL) {
1303
        testError (conn, VIR_ERR_NO_NETWORK, NULL);
1304 1305 1306
        return NULL;
    }

1307
    return virGetNetwork(conn, net->def->name, net->def->uuid);
1308 1309 1310 1311
}


static int testNumNetworks(virConnectPtr conn) {
1312
    int numActive = 0, i;
1313
    GET_CONNECTION(conn);
1314

1315 1316
    for (i = 0 ; i < privconn->networks.count ; i++)
        if (virNetworkIsActive(privconn->networks.objs[i]))
1317
            numActive++;
1318

1319
    return numActive;
1320 1321 1322
}

static int testListNetworks(virConnectPtr conn, char **const names, int nnames) {
1323
    int n = 0, i;
1324
    GET_CONNECTION(conn);
1325

1326
    memset(names, 0, sizeof(*names)*nnames);
1327 1328 1329
    for (i = 0 ; i < privconn->networks.count && n < nnames ; i++)
        if (virNetworkIsActive(privconn->networks.objs[i]) &&
            !(names[n++] = strdup(privconn->networks.objs[i]->def->name)))
1330
            goto no_memory;
1331

1332 1333 1334
    return n;

no_memory:
1335
    testError(conn, VIR_ERR_NO_MEMORY, NULL);
1336 1337 1338
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
    return (-1);
1339 1340 1341
}

static int testNumDefinedNetworks(virConnectPtr conn) {
1342
    int numInactive = 0, i;
1343
    GET_CONNECTION(conn);
1344

1345 1346
    for (i = 0 ; i < privconn->networks.count ; i++)
        if (!virNetworkIsActive(privconn->networks.objs[i]))
1347
            numInactive++;
1348

1349
    return numInactive;
1350 1351 1352
}

static int testListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
1353
    int n = 0, i;
1354
    GET_CONNECTION(conn);
1355

1356
    memset(names, 0, sizeof(*names)*nnames);
1357 1358 1359
    for (i = 0 ; i < privconn->networks.count && n < nnames ; i++)
        if (!virNetworkIsActive(privconn->networks.objs[i]) &&
            !(names[n++] = strdup(privconn->networks.objs[i]->def->name)))
1360
            goto no_memory;
1361

1362 1363 1364
    return n;

no_memory:
1365
    testError(conn, VIR_ERR_NO_MEMORY, NULL);
1366 1367 1368
    for (n = 0 ; n < nnames ; n++)
        VIR_FREE(names[n]);
    return (-1);
1369 1370 1371
}

static virNetworkPtr testNetworkCreate(virConnectPtr conn, const char *xml) {
1372 1373
    virNetworkDefPtr def;
    virNetworkObjPtr net;
1374
    GET_CONNECTION(conn);
1375

1376 1377
    if ((def = virNetworkDefParseString(conn, xml)) == NULL)
        return NULL;
1378

1379 1380 1381 1382
    if ((net = virNetworkAssignDef(conn, &privconn->networks,
                                   def)) == NULL) {
        virNetworkDefFree(def);
        return NULL;
1383
    }
1384
    net->active = 1;
1385

1386
    return virGetNetwork(conn, def->name, def->uuid);
1387 1388 1389
}

static virNetworkPtr testNetworkDefine(virConnectPtr conn, const char *xml) {
1390 1391
    virNetworkDefPtr def;
    virNetworkObjPtr net;
1392
    GET_CONNECTION(conn);
1393

1394 1395
    if ((def = virNetworkDefParseString(conn, xml)) == NULL)
        return NULL;
1396

1397 1398 1399 1400
    if ((net = virNetworkAssignDef(conn, &privconn->networks,
                                   def)) == NULL) {
        virNetworkDefFree(def);
        return NULL;
1401
    }
1402
    net->persistent = 1;
1403

1404
    return virGetNetwork(conn, def->name, def->uuid);
1405 1406 1407 1408 1409
}

static int testNetworkUndefine(virNetworkPtr network) {
    GET_NETWORK(network, -1);

1410
    if (virNetworkIsActive(privnet)) {
1411 1412
        testError(network->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Network '%s' is still running"), network->name);
1413 1414 1415
        return (-1);
    }

1416 1417
    virNetworkRemoveInactive(&privconn->networks,
                             privnet);
1418 1419 1420 1421 1422 1423 1424

    return (0);
}

static int testNetworkStart(virNetworkPtr network) {
    GET_NETWORK(network, -1);

1425
    if (virNetworkIsActive(privnet)) {
1426 1427
        testError(network->conn, VIR_ERR_INTERNAL_ERROR,
                  _("Network '%s' is already running"), network->name);
1428 1429 1430
        return (-1);
    }

1431
    privnet->active = 1;
1432 1433 1434 1435 1436 1437 1438

    return (0);
}

static int testNetworkDestroy(virNetworkPtr network) {
    GET_NETWORK(network, -1);

1439 1440 1441 1442
    privnet->active = 0;
    if (!privnet->persistent) {
        virNetworkRemoveInactive(&privconn->networks,
                                 privnet);
1443 1444 1445 1446 1447 1448 1449
    }
    return (0);
}

static char *testNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) {
    GET_NETWORK(network, NULL);

1450
    return virNetworkDefFormat(network->conn, privnet->def);
1451 1452 1453
}

static char *testNetworkGetBridgeName(virNetworkPtr network) {
1454
    char *bridge = NULL;
1455
    GET_NETWORK(network, NULL);
1456 1457
    if (privnet->def->bridge &&
        !(bridge = strdup(privnet->def->bridge))) {
1458
        testError(network->conn, VIR_ERR_NO_MEMORY, "network");
1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474
        return NULL;
    }
    return bridge;
}

static int testNetworkGetAutostart(virNetworkPtr network,
                                   int *autostart) {
    GET_NETWORK(network, -1);
    *autostart = privnet->autostart;
    return (0);
}

static int testNetworkSetAutostart(virNetworkPtr network,
                                   int autostart) {
    GET_NETWORK(network, -1);
    privnet->autostart = autostart ? 1 : 0;
1475 1476
    return (0);
}
1477

1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493
static virDrvOpenStatus testStorageOpen(virConnectPtr conn,
                                        xmlURIPtr uri ATTRIBUTE_UNUSED,
                                        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;
}

1494 1495 1496 1497 1498

static virDriver testDriver = {
    VIR_DRV_TEST,
    "Test",
    LIBVIR_VERSION_NUMBER,
1499
    NULL, /* probe */
1500 1501
    testOpen, /* open */
    testClose, /* close */
1502
    NULL, /* supports_feature */
1503 1504 1505 1506 1507 1508 1509 1510 1511
    NULL, /* type */
    testGetVersion, /* version */
    testGetHostname, /* hostname */
    testGetURI, /* URI */
    testGetMaxVCPUs, /* getMaxVcpus */
    testNodeGetInfo, /* nodeGetInfo */
    testGetCapabilities, /* getCapabilities */
    testListDomains, /* listDomains */
    testNumOfDomains, /* numOfDomains */
1512
    testDomainCreateXML, /* domainCreateXML */
1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545
    testLookupDomainByID, /* domainLookupByID */
    testLookupDomainByUUID, /* domainLookupByUUID */
    testLookupDomainByName, /* domainLookupByName */
    testPauseDomain, /* domainSuspend */
    testResumeDomain, /* domainResume */
    testShutdownDomain, /* domainShutdown */
    testRebootDomain, /* domainReboot */
    testDestroyDomain, /* domainDestroy */
    testGetOSType, /* domainGetOSType */
    testGetMaxMemory, /* domainGetMaxMemory */
    testSetMaxMemory, /* domainSetMaxMemory */
    testSetMemory, /* domainSetMemory */
    testGetDomainInfo, /* domainGetInfo */
    testDomainSave, /* domainSave */
    testDomainRestore, /* domainRestore */
    testDomainCoreDump, /* domainCoreDump */
    testSetVcpus, /* domainSetVcpus */
    NULL, /* domainPinVcpu */
    NULL, /* domainGetVcpus */
    NULL, /* domainGetMaxVcpus */
    testDomainDumpXML, /* domainDumpXML */
    testListDefinedDomains, /* listDefinedDomains */
    testNumOfDefinedDomains, /* numOfDefinedDomains */
    testDomainCreate, /* domainCreate */
    testDomainDefineXML, /* domainDefineXML */
    testDomainUndefine, /* domainUndefine */
    NULL, /* domainAttachDevice */
    NULL, /* domainDetachDevice */
    testDomainGetAutostart, /* domainGetAutostart */
    testDomainSetAutostart, /* domainSetAutostart */
    testDomainGetSchedulerType, /* domainGetSchedulerType */
    testDomainGetSchedulerParams, /* domainGetSchedulerParameters */
    testDomainSetSchedulerParams, /* domainSetSchedulerParameters */
1546 1547 1548
    NULL, /* domainMigratePrepare */
    NULL, /* domainMigratePerform */
    NULL, /* domainMigrateFinish */
1549 1550
    NULL, /* domainBlockStats */
    NULL, /* domainInterfaceStats */
R
Richard W.M. Jones 已提交
1551
    NULL, /* domainBlockPeek */
R
Richard W.M. Jones 已提交
1552
    NULL, /* domainMemoryPeek */
1553
    testNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
1554
    NULL, /* getFreeMemory */
1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578
};

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


1579 1580 1581 1582 1583 1584
static virStorageDriver testStorageDriver = {
    .name = "Test",
    .open = testStorageOpen,
    .close = testStorageClose,
};

1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596
/**
 * testRegister:
 *
 * Registers the test driver
 */
int
testRegister(void)
{
    if (virRegisterDriver(&testDriver) < 0)
        return -1;
    if (virRegisterNetworkDriver(&testNetworkDriver) < 0)
        return -1;
1597 1598
    if (virRegisterStorageDriver(&testStorageDriver) < 0)
        return -1;
1599 1600
    return 0;
}