xen_unified.c 34.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * xen_unified.c: Unified Xen driver.
 *
 * Copyright (C) 2007 Red Hat, Inc.
 *
 * See COPYING.LIB for the License of this software
 *
 * Richard W.M. Jones <rjones@redhat.com>
 */

#ifdef WITH_XEN

/* Note:
 *
 * This driver provides a unified interface to the five
 * separate underlying Xen drivers (xen_internal, proxy_internal,
 * xend_internal, xs_internal and xm_internal).  Historically
 * the body of libvirt.c handled the five Xen drivers,
 * and contained Xen-specific code.
 */

#include <stdint.h>
#include <unistd.h>
24
#include <string.h>
25
#include <errno.h>
26 27
#include <sys/types.h>
#include <xen/dom0_ops.h>
28
#include <libxml/uri.h>
29 30 31 32 33 34 35 36 37 38

#include "internal.h"

#include "xen_unified.h"

#include "xen_internal.h"
#include "proxy_internal.h"
#include "xend_internal.h"
#include "xs_internal.h"
#include "xm_internal.h"
39
#include "xml.h"
40

41 42
static int
xenUnifiedNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info);
43 44 45 46 47 48
static int
xenUnifiedDomainGetMaxVcpus (virDomainPtr dom);
static int
xenUnifiedDomainGetVcpus (virDomainPtr dom,
                          virVcpuInfoPtr info, int maxinfo,
                          unsigned char *cpumaps, int maplen);
49

50
/* The five Xen drivers below us. */
51 52 53 54 55 56
static struct xenUnifiedDriver *drivers[XEN_UNIFIED_NR_DRIVERS] = {
    [XEN_UNIFIED_HYPERVISOR_OFFSET] = &xenHypervisorDriver,
    [XEN_UNIFIED_PROXY_OFFSET] = &xenProxyDriver,
    [XEN_UNIFIED_XEND_OFFSET] = &xenDaemonDriver,
    [XEN_UNIFIED_XS_OFFSET] = &xenStoreDriver,
    [XEN_UNIFIED_XM_OFFSET] = &xenXMDriver,
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
};

/**
 * xenUnifiedError:
 * @conn: the connection
 * @error: the error number
 * @info: extra information string
 *
 * Handle an error at the xend daemon interface
 */
static void
xenUnifiedError (virConnectPtr conn, virErrorNumber error, const char *info)
{
    const char *errmsg;

    errmsg = __virErrorMsg (error, info);
    __virRaiseError (conn, NULL, NULL, VIR_FROM_XEN, error, VIR_ERR_ERROR,
74
                     errmsg, info, NULL, 0, 0, errmsg, info);
75 76
}

77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
/*
 * Helper functions currently used in the NUMA code
 * Those variables should not be accessed directly but through helper 
 * functions xenNbCells() and xenNbCpu() available to all Xen backends 
 */
static int nbNodeCells = -1;
static int nbNodeCpus = -1;

/**
 * xenNumaInit:
 * @conn: pointer to the hypervisor connection
 *
 * Initializer for previous variables. We currently assume that
 * the number of physical CPU and the numebr of NUMA cell is fixed
 * until reboot which might be false in future Xen implementations.
 */
static void
xenNumaInit(virConnectPtr conn) {
    virNodeInfo nodeInfo;
    int ret;

    ret = xenUnifiedNodeGetInfo(conn, &nodeInfo);
    if (ret < 0)
        return;
    nbNodeCells = nodeInfo.nodes;
    nbNodeCpus = nodeInfo.cpus;
}

/**
 * xenNbCells:
 * @conn: pointer to the hypervisor connection
 *
 * Number of NUMa cells present in the actual Node
 *
 * Returns the number of NUMA cells available on that Node
 */
int xenNbCells(virConnectPtr conn) {
    if (nbNodeCells < 0)
        xenNumaInit(conn);
    return(nbNodeCells);
}

/**
 * xenNbCpus:
 * @conn: pointer to the hypervisor connection
 *
123
 * Number of CPUs present in the actual Node
124
 *
125
 * Returns the number of CPUs available on that Node
126 127 128 129 130 131 132
 */
int xenNbCpus(virConnectPtr conn) {
    if (nbNodeCpus < 0)
        xenNumaInit(conn);
    return(nbNodeCpus);
}

133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
/**
 * xenDomainUsedCpus:
 * @dom: the domain
 *
 * Analyze which set of CPUs are used by the domain and
 * return a string providing the ranges.
 *
 * Returns the string which needs to be freed by the caller or
 *         NULL if the domain uses all CPU or in case of error.
 */
char *
xenDomainUsedCpus(virDomainPtr dom)
{
    char *res = NULL;
    int nb_cpu, ncpus;
    int nb_vcpu;
    char *cpulist = NULL;
    unsigned char *cpumap = NULL;
    size_t cpumaplen;
    int nb = 0;
    int n, m;
    virVcpuInfoPtr cpuinfo = NULL;
    virNodeInfo nodeinfo;

    if (!VIR_IS_CONNECTED_DOMAIN(dom))
        return (NULL);

    nb_cpu = xenNbCpus(dom->conn);
    if (nb_cpu <= 0)
        return(NULL);
    nb_vcpu = xenUnifiedDomainGetMaxVcpus(dom);
    if (nb_vcpu <= 0)
        return(NULL);
    if (xenUnifiedNodeGetInfo(dom->conn, &nodeinfo) < 0)
        return(NULL);

    cpulist = (char *) calloc(nb_cpu, sizeof(char));
    if (cpulist == NULL)
        goto done;
    cpuinfo = malloc(sizeof(virVcpuInfo) * nb_vcpu);
    if (cpuinfo == NULL)
        goto done;
    cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
    cpumap = (unsigned char *) calloc(nb_vcpu, cpumaplen);
    if (cpumap == NULL)
        goto done;

    if ((ncpus = xenUnifiedDomainGetVcpus(dom, cpuinfo, nb_vcpu,
                                          cpumap, cpumaplen)) >= 0) {
	for (n = 0 ; n < ncpus ; n++) {
	    for (m = 0 ; m < nb_cpu; m++) {
	        if ((cpulist[m] == 0) &&
	 	    (VIR_CPU_USABLE(cpumap, cpumaplen, n, m))) {
		    cpulist[m] = 1;
		    nb++;
		    /* if all CPU are used just return NULL */
		    if (nb == nb_cpu) 
		        goto done;
		        
		}
	    }
	}
        res = virSaveCpuSet(dom->conn, cpulist, nb_cpu);
    }

done:
    if (cpulist != NULL)
        free(cpulist);
    if (cpumap != NULL)
        free(cpumap);
    if (cpuinfo != NULL)
        free(cpuinfo);
    return(res);
}

208 209 210 211 212 213 214 215 216 217 218 219
/*----- Dispatch functions. -----*/

/* These dispatch functions follow the model used historically
 * by libvirt.c -- trying each low-level Xen driver in turn
 * until one succeeds.  However since we know what low-level
 * drivers can perform which functions, it is probably better
 * in future to optimise these dispatch functions to just call
 * the single function (or small number of appropriate functions)
 * in the low level drivers directly.
 */

static int
220
xenUnifiedOpen (virConnectPtr conn, xmlURIPtr uri, int flags)
221
{
222 223
    int i, j;
    xenUnifiedPrivatePtr priv;
224

225
    /* Refuse any scheme which isn't "xen://" or "http://". */
226 227
    if (uri->scheme &&
        strcasecmp(uri->scheme, "xen") != 0 &&
228
        strcasecmp(uri->scheme, "http") != 0)
229 230 231 232 233 234 235
        return VIR_DRV_OPEN_DECLINED;

    /* xmlParseURI will parse a naked string like "foo" as a URI with
     * a NULL scheme.  That's not useful for us because we want to only
     * allow full pathnames (eg. ///var/lib/xen/xend-socket).  Decline
     * anything else.
     */
236
    if (!uri->scheme && (!uri->path || uri->path[0] != '/'))
237
        return VIR_DRV_OPEN_DECLINED;
238 239

    /* Refuse any xen:// URI with a server specified - allow remote to do it */
240
    if (uri->scheme && strcasecmp(uri->scheme, "xen") == 0 && uri->server)
241
        return VIR_DRV_OPEN_DECLINED;
242 243

    /* Allocate per-connection private data. */
244
    priv = calloc (1, sizeof *priv);
245
    if (!priv) {
246
        xenUnifiedError (NULL, VIR_ERR_NO_MEMORY, "allocating private data");
247 248 249 250 251 252 253 254 255 256 257 258
        return VIR_DRV_OPEN_ERROR;
    }
    conn->privateData = priv;

    priv->handle = -1;
    priv->xendConfigVersion = -1;
    priv->type = -1;
    priv->len = -1;
    priv->addr = NULL;
    priv->xshandle = NULL;
    priv->proxy = -1;

259 260
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) {
        priv->opened[i] = 0;
261

262 263 264 265 266
        /* Only use XM driver for Xen <= 3.0.3 (ie xendConfigVersion <= 2) */
        if (drivers[i] == &xenXMDriver &&
            priv->xendConfigVersion > 2)
            continue;

267
        /* Ignore proxy for root */
268
        if (i == XEN_UNIFIED_PROXY_OFFSET && getuid() == 0)
269 270
            continue;

271 272 273 274
        if (drivers[i]->open) {
#ifdef ENABLE_DEBUG
            fprintf (stderr, "libvirt: xenUnifiedOpen: trying Xen sub-driver %d\n", i);
#endif
275
            if (drivers[i]->open (conn, uri, flags) == VIR_DRV_OPEN_SUCCESS)
276 277 278 279 280 281
                priv->opened[i] = 1;
#ifdef ENABLE_DEBUG
            fprintf (stderr, "libvirt: xenUnifiedOpen: Xen sub-driver %d open %s\n",
                     i, priv->opened[i] ? "ok" : "failed");
#endif
        }
282 283 284

        /* If as root, then all drivers must succeed.
           If non-root, then only proxy must succeed */
285 286
        if (!priv->opened[i] &&
            (getuid() == 0 || i == XEN_UNIFIED_PROXY_OFFSET)) {
287
            for (j = 0; j < i; ++j)
288
                if (priv->opened[j]) drivers[j]->close (conn);
289 290 291 292
            free (priv);
            /* The assumption is that one of the underlying drivers
             * has set virterror already.
             */
293 294
            return VIR_DRV_OPEN_ERROR;
        }
295 296
    }

297
    return VIR_DRV_OPEN_SUCCESS;
298 299
}

300 301 302
#define GET_PRIVATE(conn) \
    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) (conn)->privateData

303 304 305
static int
xenUnifiedClose (virConnectPtr conn)
{
306
    GET_PRIVATE(conn);
307
    int i;
308

309 310
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->close)
311
            (void) drivers[i]->close (conn);
312

313 314
    free (conn->privateData);
    conn->privateData = NULL;
315

316
    return 0;
317 318 319 320 321
}

static const char *
xenUnifiedType (virConnectPtr conn)
{
322
    GET_PRIVATE(conn);
323 324
    int i;
    const char *ret;
325

326 327
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->type) {
328 329 330
            ret = drivers[i]->type (conn);
            if (ret) return ret;
        }
331

332
    return NULL;
333 334
}

335 336 337 338 339 340 341 342 343 344
/* Which features are supported by this driver? */
static int
xenUnifiedSupportsFeature (virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
{
    switch (feature) {
    case VIR_DRV_FEATURE_MIGRATION_V1: return 1;
    default: return 0;
    }
}

345 346 347
static int
xenUnifiedVersion (virConnectPtr conn, unsigned long *hvVer)
{
348
    GET_PRIVATE(conn);
349
    int i;
350

351 352 353
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->version &&
354 355
            drivers[i]->version (conn, hvVer) == 0)
            return 0;
356

357
    return -1;
358 359
}

360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
/* NB: Even if connected to the proxy, we're still on the
 * same machine.
 */
static char *
xenUnifiedGetHostname (virConnectPtr conn)
{
    int r;
    char hostname [HOST_NAME_MAX+1], *str;

    r = gethostname (hostname, HOST_NAME_MAX+1);
    if (r == -1) {
        xenUnifiedError (conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
        return NULL;
    }
    str = strdup (hostname);
    if (str == NULL) {
        xenUnifiedError (conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
        return NULL;
    }
    return str;
}

382 383 384
static int
xenUnifiedGetMaxVcpus (virConnectPtr conn, const char *type)
{
385
    GET_PRIVATE(conn);
386

387 388 389 390
    if (type && STRCASENEQ (type, "Xen")) {
        xenUnifiedError (conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
        return -1;
    }
391

392 393 394 395 396 397
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
        return xenHypervisorGetMaxVcpus (conn, type);
    else {
        xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
        return -1;
    }
398 399 400 401 402
}

static int
xenUnifiedNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info)
{
403
    GET_PRIVATE(conn);
404
    int i;
405

406 407 408
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->nodeGetInfo &&
409 410
            drivers[i]->nodeGetInfo (conn, info) == 0)
            return 0;
411

412
    return -1;
413 414 415 416 417
}

static char *
xenUnifiedGetCapabilities (virConnectPtr conn)
{
418
    GET_PRIVATE(conn);
419 420
    int i;
    char *ret;
421

422 423
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->getCapabilities) {
424 425 426
            ret = drivers[i]->getCapabilities (conn);
            if (ret) return ret;
        }
427

428
    return NULL;
429 430 431 432 433
}

static int
xenUnifiedListDomains (virConnectPtr conn, int *ids, int maxids)
{
434
    GET_PRIVATE(conn);
435
    int i, ret;
436

437 438
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->listDomains) {
439 440 441
            ret = drivers[i]->listDomains (conn, ids, maxids);
            if (ret >= 0) return ret;
        }
442

443
    return -1;
444 445 446 447 448
}

static int
xenUnifiedNumOfDomains (virConnectPtr conn)
{
449
    GET_PRIVATE(conn);
450
    int i, ret;
451

452 453
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->numOfDomains) {
454 455 456
            ret = drivers[i]->numOfDomains (conn);
            if (ret >= 0) return ret;
        }
457

458
    return -1;
459 460 461 462
}

static virDomainPtr
xenUnifiedDomainCreateLinux (virConnectPtr conn,
463
                             const char *xmlDesc, unsigned int flags)
464
{
465
    GET_PRIVATE(conn);
466 467
    int i;
    virDomainPtr ret;
468

469 470
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->domainCreateLinux) {
471 472 473
            ret = drivers[i]->domainCreateLinux (conn, xmlDesc, flags);
            if (ret) return ret;
        }
474

475
    return NULL;
476 477
}

478 479 480 481
/* Assumption made in underlying drivers:
 * If the domain is "not found" and there is no other error, then
 * the Lookup* functions return a NULL but do not set virterror.
 */
482 483 484
static virDomainPtr
xenUnifiedDomainLookupByID (virConnectPtr conn, int id)
{
485
    GET_PRIVATE(conn);
486
    virDomainPtr ret;
487

488 489 490 491 492
    /* Reset any connection-level errors in virterror first, in case
     * there is one hanging around from a previous call.
     */
    virConnResetLastError (conn);

493 494 495 496 497 498 499
    /* Try hypervisor/xenstore combo. */
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
        ret = xenHypervisorLookupDomainByID (conn, id);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }

500 501 502 503 504 505 506 507 508 509 510 511 512
    /* Try proxy. */
    if (priv->opened[XEN_UNIFIED_PROXY_OFFSET]) {
        ret = xenProxyLookupByID (conn, id);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }

    /* Try xend. */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
        ret = xenDaemonLookupByID (conn, id);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }
513

514 515
    /* Not found. */
    xenUnifiedError (conn, VIR_ERR_NO_DOMAIN, __FUNCTION__);
516
    return NULL;
517 518 519 520
}

static virDomainPtr
xenUnifiedDomainLookupByUUID (virConnectPtr conn,
521
                              const unsigned char *uuid)
522
{
523
    GET_PRIVATE(conn);
524
    virDomainPtr ret;
525

526 527 528 529 530
    /* Reset any connection-level errors in virterror first, in case
     * there is one hanging around from a previous call.
     */
    virConnResetLastError (conn);

531 532 533 534 535 536 537
    /* Try hypervisor/xenstore combo. */
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
        ret = xenHypervisorLookupDomainByUUID (conn, uuid);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }

538 539 540 541 542 543 544 545 546 547 548 549 550
    /* Try proxy. */
    if (priv->opened[XEN_UNIFIED_PROXY_OFFSET]) {
        ret = xenProxyLookupByUUID (conn, uuid);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }

    /* Try xend. */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
        ret = xenDaemonLookupByUUID (conn, uuid);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }
551

552 553 554 555 556 557 558 559 560
    /* Try XM for inactive domains. */
    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
        ret = xenXMDomainLookupByUUID (conn, uuid);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }

    /* Not found. */
    xenUnifiedError (conn, VIR_ERR_NO_DOMAIN, __FUNCTION__);
561
    return NULL;
562 563 564 565
}

static virDomainPtr
xenUnifiedDomainLookupByName (virConnectPtr conn,
566
                              const char *name)
567
{
568
    GET_PRIVATE(conn);
569
    virDomainPtr ret;
570

571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
    /* Reset any connection-level errors in virterror first, in case
     * there is one hanging around from a previous call.
     */
    virConnResetLastError (conn);

    /* Try proxy. */
    if (priv->opened[XEN_UNIFIED_PROXY_OFFSET]) {
        ret = xenProxyLookupByName (conn, name);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }

    /* Try xend. */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
        ret = xenDaemonLookupByName (conn, name);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }

    /* Try xenstore for inactive domains. */
    if (priv->opened[XEN_UNIFIED_XS_OFFSET]) {
        ret = xenStoreLookupByName (conn, name);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }

    /* Try XM for inactive domains. */
    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
        ret = xenXMDomainLookupByName (conn, name);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }
603

604 605
    /* Not found. */
    xenUnifiedError (conn, VIR_ERR_NO_DOMAIN, __FUNCTION__);
606
    return NULL;
607 608 609 610 611
}

static int
xenUnifiedDomainSuspend (virDomainPtr dom)
{
612
    GET_PRIVATE(dom->conn);
613
    int i;
614

615 616 617
    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
618
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
619
        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
620
            priv->opened[i] &&
621 622 623
            drivers[i]->domainSuspend &&
            drivers[i]->domainSuspend (dom) == 0)
            return 0;
624

625 626 627
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSuspend &&
        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSuspend (dom) == 0)
628
        return 0;
629

630
    return -1;
631 632 633 634 635
}

static int
xenUnifiedDomainResume (virDomainPtr dom)
{
636
    GET_PRIVATE(dom->conn);
637
    int i;
638

639 640 641
    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
642
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
643
        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
644
            priv->opened[i] &&
645 646 647
            drivers[i]->domainResume &&
            drivers[i]->domainResume (dom) == 0)
            return 0;
648

649 650 651
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainResume &&
        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainResume (dom) == 0)
652
        return 0;
653

654
    return -1;
655 656 657 658 659
}

static int
xenUnifiedDomainShutdown (virDomainPtr dom)
{
660
    GET_PRIVATE(dom->conn);
661
    int i;
662

663 664 665
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->domainShutdown &&
666 667
            drivers[i]->domainShutdown (dom) == 0)
            return 0;
668

669
    return -1;
670 671 672 673 674
}

static int
xenUnifiedDomainReboot (virDomainPtr dom, unsigned int flags)
{
675
    GET_PRIVATE(dom->conn);
676
    int i;
677

678 679 680
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->domainReboot &&
681 682
            drivers[i]->domainReboot (dom, flags) == 0)
            return 0;
683

684
    return -1;
685 686 687 688 689
}

static int
xenUnifiedDomainDestroy (virDomainPtr dom)
{
690
    GET_PRIVATE(dom->conn);
691
    int i;
692

693 694 695
    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
696
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
697
        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
698
            priv->opened[i] &&
699 700 701
            drivers[i]->domainDestroy &&
            drivers[i]->domainDestroy (dom) == 0)
            return 0;
702

703
    if (priv->opened[i] &&
704 705
        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainDestroy &&
        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainDestroy (dom) == 0)
706
        return 0;
707

708
    return -1;
709 710 711 712 713
}

static char *
xenUnifiedDomainGetOSType (virDomainPtr dom)
{
714
    GET_PRIVATE(dom->conn);
715 716
    int i;
    char *ret;
717

718 719
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->domainGetOSType) {
720 721 722
            ret = drivers[i]->domainGetOSType (dom);
            if (ret) return ret;
        }
723

724
    return NULL;
725 726 727 728 729
}

static unsigned long
xenUnifiedDomainGetMaxMemory (virDomainPtr dom)
{
730
    GET_PRIVATE(dom->conn);
731 732
    int i;
    unsigned long ret;
733

734 735
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->domainGetMaxMemory) {
736 737 738
            ret = drivers[i]->domainGetMaxMemory (dom);
            if (ret != 0) return ret;
        }
739

740
    return 0;
741 742 743 744 745
}

static int
xenUnifiedDomainSetMaxMemory (virDomainPtr dom, unsigned long memory)
{
746
    GET_PRIVATE(dom->conn);
747
    int i;
748

749 750 751
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->domainSetMaxMemory &&
752 753
            drivers[i]->domainSetMaxMemory (dom, memory) == 0)
            return 0;
754

755
    return -1;
756 757 758 759 760
}

static int
xenUnifiedDomainSetMemory (virDomainPtr dom, unsigned long memory)
{
761
    GET_PRIVATE(dom->conn);
762
    int i;
763

764 765 766
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->domainSetMemory &&
767 768
            drivers[i]->domainSetMemory (dom, memory) == 0)
            return 0;
769

770
    return -1;
771 772 773 774 775
}

static int
xenUnifiedDomainGetInfo (virDomainPtr dom, virDomainInfoPtr info)
{
776
    GET_PRIVATE(dom->conn);
777
    int i;
778

779 780 781
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->domainGetInfo &&
782 783
            drivers[i]->domainGetInfo (dom, info) == 0)
            return 0;
784

785
    return -1;
786 787 788 789 790
}

static int
xenUnifiedDomainSave (virDomainPtr dom, const char *to)
{
791
    GET_PRIVATE(dom->conn);
792
    int i;
793

794 795 796
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->domainSave &&
797 798
            drivers[i]->domainSave (dom, to) == 0)
            return 0;
799

800
    return -1;
801 802 803 804 805
}

static int
xenUnifiedDomainRestore (virConnectPtr conn, const char *from)
{
806
    GET_PRIVATE(conn);
807
    int i;
808

809 810 811
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->domainRestore &&
812 813
            drivers[i]->domainRestore (conn, from) == 0)
            return 0;
814

815
    return -1;
816 817 818 819 820
}

static int
xenUnifiedDomainCoreDump (virDomainPtr dom, const char *to, int flags)
{
821
    GET_PRIVATE(dom->conn);
822
    int i;
823

824 825 826
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->domainCoreDump &&
827 828
            drivers[i]->domainCoreDump (dom, to, flags) == 0)
            return 0;
829

830
    return -1;
831 832 833 834 835
}

static int
xenUnifiedDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus)
{
836
    GET_PRIVATE(dom->conn);
837
    int i;
838

839 840 841
    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
842
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
843
        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
844
            priv->opened[i] &&
845 846 847
            drivers[i]->domainSetVcpus &&
            drivers[i]->domainSetVcpus (dom, nvcpus) == 0)
            return 0;
848

849 850 851
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSetVcpus &&
        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSetVcpus (dom, nvcpus) == 0)
852
        return 0;
853

854
    return -1;
855 856 857 858
}

static int
xenUnifiedDomainPinVcpu (virDomainPtr dom, unsigned int vcpu,
859
                         unsigned char *cpumap, int maplen)
860
{
861
    GET_PRIVATE(dom->conn);
862
    int i;
863

864 865 866
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->domainPinVcpu &&
867 868
            drivers[i]->domainPinVcpu (dom, vcpu, cpumap, maplen) == 0)
            return 0;
869

870
    return -1;
871 872 873 874
}

static int
xenUnifiedDomainGetVcpus (virDomainPtr dom,
875 876
                          virVcpuInfoPtr info, int maxinfo,
                          unsigned char *cpumaps, int maplen)
877
{
878
    GET_PRIVATE(dom->conn);
879
    int i, ret;
880

881 882
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->domainGetVcpus) {
883 884 885 886
            ret = drivers[i]->domainGetVcpus (dom, info, maxinfo, cpumaps, maplen);
            if (ret > 0)
                return ret;
        }
887
    return -1;
888 889 890 891 892
}

static int
xenUnifiedDomainGetMaxVcpus (virDomainPtr dom)
{
893
    GET_PRIVATE(dom->conn);
894
    int i, ret;
895

896 897
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->domainGetMaxVcpus) {
898 899 900
            ret = drivers[i]->domainGetMaxVcpus (dom);
            if (ret != 0) return ret;
        }
901

902
    return -1;
903 904 905 906 907
}

static char *
xenUnifiedDomainDumpXML (virDomainPtr dom, int flags)
{
908
    GET_PRIVATE(dom->conn);
909

910 911 912 913 914 915 916 917 918 919 920
    if (dom->id == -1 && priv->xendConfigVersion < 3 ) {
        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
            return xenXMDomainDumpXML(dom, flags);
    } else {
        if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
            char *cpus, *res;
            cpus = xenDomainUsedCpus(dom);
            res = xenDaemonDomainDumpXML(dom, flags, cpus);
	    if (cpus != NULL)
	        free(cpus);
	    return(res);
921
        }
922 923 924
        if (priv->opened[XEN_UNIFIED_PROXY_OFFSET])
            return xenProxyDomainDumpXML(dom, flags);
    } 
925

926
    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
927
    return NULL;
928 929
}

930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980
static int
xenUnifiedDomainMigratePrepare (virConnectPtr dconn,
                                char **cookie,
                                int *cookielen,
                                const char *uri_in,
                                char **uri_out,
                                unsigned long flags,
                                const char *dname,
                                unsigned long resource)
{
    GET_PRIVATE(dconn);

    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonDomainMigratePrepare (dconn, cookie, cookielen,
                                              uri_in, uri_out,
                                              flags, dname, resource);

    xenUnifiedError (dconn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
    return -1;
}

static int
xenUnifiedDomainMigratePerform (virDomainPtr dom,
                                const char *cookie,
                                int cookielen,
                                const char *uri,
                                unsigned long flags,
                                const char *dname,
                                unsigned long resource)
{
    GET_PRIVATE(dom->conn);

    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonDomainMigratePerform (dom, cookie, cookielen, uri,
                                              flags, dname, resource);

    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
    return -1;
}

static virDomainPtr
xenUnifiedDomainMigrateFinish (virConnectPtr dconn,
                               const char *dname,
                               const char *cookie ATTRIBUTE_UNUSED,
                               int cookielen ATTRIBUTE_UNUSED,
                               const char *uri ATTRIBUTE_UNUSED,
                               unsigned long flags ATTRIBUTE_UNUSED)
{
    return xenUnifiedDomainLookupByName (dconn, dname);
}

981 982
static int
xenUnifiedListDefinedDomains (virConnectPtr conn, char **const names,
983
                              int maxnames)
984
{
985
    GET_PRIVATE(conn);
986 987
    int i;
    int ret;
988

989 990
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->listDefinedDomains) {
991 992 993
            ret = drivers[i]->listDefinedDomains (conn, names, maxnames);
            if (ret >= 0) return ret;
        }
994

995
    return -1;
996 997 998 999 1000
}

static int
xenUnifiedNumOfDefinedDomains (virConnectPtr conn)
{
1001
    GET_PRIVATE(conn);
1002 1003
    int i;
    int ret;
1004

1005 1006
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->numOfDefinedDomains) {
1007 1008 1009
            ret = drivers[i]->numOfDefinedDomains (conn);
            if (ret >= 0) return ret;
        }
1010

1011
    return -1;
1012 1013 1014 1015 1016
}

static int
xenUnifiedDomainCreate (virDomainPtr dom)
{
1017
    GET_PRIVATE(dom->conn);
1018
    int i;
1019

1020 1021
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->domainCreate &&
1022 1023
            drivers[i]->domainCreate (dom) == 0)
            return 0;
1024

1025
    return -1;
1026 1027 1028 1029 1030
}

static virDomainPtr
xenUnifiedDomainDefineXML (virConnectPtr conn, const char *xml)
{
1031
    GET_PRIVATE(conn);
1032 1033
    int i;
    virDomainPtr ret;
1034

1035 1036
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->domainDefineXML) {
1037 1038 1039
            ret = drivers[i]->domainDefineXML (conn, xml);
            if (ret) return ret;
        }
1040

1041
    return NULL;
1042 1043 1044 1045 1046
}

static int
xenUnifiedDomainUndefine (virDomainPtr dom)
{
1047
    GET_PRIVATE(dom->conn);
1048
    int i;
1049

1050 1051
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->domainUndefine &&
1052 1053
            drivers[i]->domainUndefine (dom) == 0)
            return 0;
1054

1055
    return -1;
1056 1057 1058
}

static int
1059
xenUnifiedDomainAttachDevice (virDomainPtr dom, const char *xml)
1060
{
1061
    GET_PRIVATE(dom->conn);
1062
    int i;
1063

1064 1065
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->domainAttachDevice &&
1066 1067
            drivers[i]->domainAttachDevice (dom, xml) == 0)
            return 0;
1068

1069
    return -1;
1070 1071 1072
}

static int
1073
xenUnifiedDomainDetachDevice (virDomainPtr dom, const char *xml)
1074
{
1075
    GET_PRIVATE(dom->conn);
1076
    int i;
1077

1078 1079
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->domainDetachDevice &&
1080 1081
            drivers[i]->domainDetachDevice (dom, xml) == 0)
            return 0;
1082

1083
    return -1;
1084 1085
}

1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
static char *
xenUnifiedDomainGetSchedulerType (virDomainPtr dom, int *nparams)
{
    GET_PRIVATE(dom->conn);
    int i;
    char *schedulertype;

    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; i++) {
        if (priv->opened[i] && drivers[i]->domainGetSchedulerType) {
            schedulertype = drivers[i]->domainGetSchedulerType (dom, nparams);
	    if (schedulertype != NULL)
		return(schedulertype); 
        }
    }
    return(NULL);
}

static int
xenUnifiedDomainGetSchedulerParameters (virDomainPtr dom,
                    virSchedParameterPtr params, int *nparams)
{
    GET_PRIVATE(dom->conn);
    int i, ret;

    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) {
        if (priv->opened[i] && drivers[i]->domainGetSchedulerParameters) {
           ret = drivers[i]->domainGetSchedulerParameters(dom, params, nparams);
	   if (ret == 0)
	       return(0);
	}
    }
    return(-1);
}

static int
xenUnifiedDomainSetSchedulerParameters (virDomainPtr dom,
                    virSchedParameterPtr params, int nparams)
{
    GET_PRIVATE(dom->conn);
    int i, ret;

    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) {
        if (priv->opened[i] && drivers[i]->domainSetSchedulerParameters) {
           ret = drivers[i]->domainSetSchedulerParameters(dom, params, nparams);
	   if (ret == 0)
	       return 0;
	}
    }

    return(-1);
}

1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163
static int
xenUnifiedDomainBlockStats (virDomainPtr dom, const char *path,
                            struct _virDomainBlockStats *stats)
{
    GET_PRIVATE (dom->conn);

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
        return xenHypervisorDomainBlockStats (dom, path, stats);

    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
    return -1;
}

static int
xenUnifiedDomainInterfaceStats (virDomainPtr dom, const char *path,
                                struct _virDomainInterfaceStats *stats)
{
    GET_PRIVATE (dom->conn);

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
        return xenHypervisorDomainInterfaceStats (dom, path, stats);

    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
    return -1;
}

1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177
static int
xenUnifiedNodeGetCellsFreeMemory (virConnectPtr conn, unsigned long long *freeMems,
                                  int startCell, int maxCells)
{
    GET_PRIVATE (conn);

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
        return xenHypervisorNodeGetCellsFreeMemory (conn, freeMems, 
                                                    startCell, maxCells);

    xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
    return -1;
}

1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196
static unsigned long long
xenUnifiedNodeGetFreeMemory (virConnectPtr conn)
{
    unsigned long long freeMem = 0;
    int ret;
    GET_PRIVATE (conn);

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
        ret = xenHypervisorNodeGetCellsFreeMemory (conn, &freeMem, 
                                                    -1, 1);
	if (ret != 1)
	    return (0);
	return(freeMem);
    }

    xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
    return(0);
}

1197 1198
/*----- Register with libvirt.c, and initialise Xen drivers. -----*/

1199 1200 1201
#define VERSION ((DOM0_INTERFACE_VERSION >> 24) * 1000000 +         \
                 ((DOM0_INTERFACE_VERSION >> 16) & 0xFF) * 1000 +	\
                 (DOM0_INTERFACE_VERSION & 0xFFFF))
1202 1203 1204

/* The interface which we export upwards to libvirt.c. */
static virDriver xenUnifiedDriver = {
1205
    .no = VIR_DRV_XEN_UNIFIED,
1206
    .name = "Xen",
1207 1208 1209
    .ver = VERSION,
    .open 			= xenUnifiedOpen,
    .close 			= xenUnifiedClose,
1210
    .supports_feature   = xenUnifiedSupportsFeature,
1211 1212
    .type 			= xenUnifiedType,
    .version 			= xenUnifiedVersion,
1213
    .getHostname    = xenUnifiedGetHostname,
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247
    .getMaxVcpus 			= xenUnifiedGetMaxVcpus,
    .nodeGetInfo 			= xenUnifiedNodeGetInfo,
    .getCapabilities 		= xenUnifiedGetCapabilities,
    .listDomains 			= xenUnifiedListDomains,
    .numOfDomains 		= xenUnifiedNumOfDomains,
    .domainCreateLinux 		= xenUnifiedDomainCreateLinux,
    .domainLookupByID 		= xenUnifiedDomainLookupByID,
    .domainLookupByUUID 		= xenUnifiedDomainLookupByUUID,
    .domainLookupByName 		= xenUnifiedDomainLookupByName,
    .domainSuspend 		= xenUnifiedDomainSuspend,
    .domainResume 		= xenUnifiedDomainResume,
    .domainShutdown 		= xenUnifiedDomainShutdown,
    .domainReboot 		= xenUnifiedDomainReboot,
    .domainDestroy 		= xenUnifiedDomainDestroy,
    .domainGetOSType 		= xenUnifiedDomainGetOSType,
    .domainGetMaxMemory 		= xenUnifiedDomainGetMaxMemory,
    .domainSetMaxMemory 		= xenUnifiedDomainSetMaxMemory,
    .domainSetMemory 		= xenUnifiedDomainSetMemory,
    .domainGetInfo 		= xenUnifiedDomainGetInfo,
    .domainSave 			= xenUnifiedDomainSave,
    .domainRestore 		= xenUnifiedDomainRestore,
    .domainCoreDump 		= xenUnifiedDomainCoreDump,
    .domainSetVcpus 		= xenUnifiedDomainSetVcpus,
    .domainPinVcpu 		= xenUnifiedDomainPinVcpu,
    .domainGetVcpus 		= xenUnifiedDomainGetVcpus,
    .domainGetMaxVcpus 		= xenUnifiedDomainGetMaxVcpus,
    .domainDumpXML 		= xenUnifiedDomainDumpXML,
    .listDefinedDomains 		= xenUnifiedListDefinedDomains,
    .numOfDefinedDomains 		= xenUnifiedNumOfDefinedDomains,
    .domainCreate 		= xenUnifiedDomainCreate,
    .domainDefineXML 		= xenUnifiedDomainDefineXML,
    .domainUndefine 		= xenUnifiedDomainUndefine,
    .domainAttachDevice 		= xenUnifiedDomainAttachDevice,
    .domainDetachDevice 		= xenUnifiedDomainDetachDevice,
1248 1249 1250
    .domainGetSchedulerType	= xenUnifiedDomainGetSchedulerType,
    .domainGetSchedulerParameters	= xenUnifiedDomainGetSchedulerParameters,
    .domainSetSchedulerParameters	= xenUnifiedDomainSetSchedulerParameters,
1251 1252 1253
    .domainMigratePrepare		= xenUnifiedDomainMigratePrepare,
    .domainMigratePerform		= xenUnifiedDomainMigratePerform,
    .domainMigrateFinish		= xenUnifiedDomainMigrateFinish,
1254 1255
    .domainBlockStats	= xenUnifiedDomainBlockStats,
    .domainInterfaceStats = xenUnifiedDomainInterfaceStats,
1256
    .nodeGetCellsFreeMemory = xenUnifiedNodeGetCellsFreeMemory,
1257
    .getFreeMemory = xenUnifiedNodeGetFreeMemory,
1258 1259
};

1260 1261 1262 1263 1264 1265 1266
/**
 * xenUnifiedRegister:
 *
 * Register xen related drivers
 *
 * Returns the driver priority or -1 in case of error.
 */
1267 1268 1269
int
xenUnifiedRegister (void)
{
1270 1271 1272 1273 1274 1275
    /* Ignore failures here. */
    (void) xenHypervisorInit ();
    (void) xenProxyInit ();
    (void) xenDaemonInit ();
    (void) xenStoreInit ();
    (void) xenXMInit ();
1276

1277
    return virRegisterDriver (&xenUnifiedDriver);
1278 1279 1280
}

#endif /* WITH_XEN */
1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294

/*
 * vim: set tabstop=4:
 * vim: set shiftwidth=4:
 * vim: set expandtab:
 */
/*
 * Local variables:
 *  indent-tabs-mode: nil
 *  c-indent-level: 4
 *  c-basic-offset: 4
 *  tab-width: 4
 * End:
 */