xen_driver.c 68.5 KB
Newer Older
1
/*
2
 * xen_driver.c: Unified Xen driver.
3
 *
4
 * Copyright (C) 2007-2012 Red Hat, Inc.
5
 *
O
Osier Yang 已提交
6 7 8 9 10 11 12 13 14 15 16
 * 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
17
 * License along with this library.  If not, see
O
Osier Yang 已提交
18
 * <http://www.gnu.org/licenses/>.
19 20 21 22
 *
 * Richard W.M. Jones <rjones@redhat.com>
 */

23
#include <config.h>
24

25 26 27
/* Note:
 *
 * This driver provides a unified interface to the five
28
 * separate underlying Xen drivers (xen_internal,
29 30 31 32 33 34 35
 * 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>
36
#include <string.h>
37
#include <errno.h>
38
#include <sys/types.h>
39
#include <fcntl.h>
40 41
#include <xen/dom0_ops.h>

42
#include "virerror.h"
43
#include "virlog.h"
44
#include "datatypes.h"
45
#include "xen_driver.h"
46

47
#include "xen_sxpr.h"
48
#include "xen_xm.h"
49
#include "xen_hypervisor.h"
50 51 52
#include "xend_internal.h"
#include "xs_internal.h"
#include "xm_internal.h"
53
#if WITH_XEN_INOTIFY
54
# include "xen_inotify.h"
55
#endif
56
#include "virxml.h"
57
#include "virutil.h"
58
#include "viralloc.h"
59
#include "node_device_conf.h"
60
#include "virpci.h"
61
#include "viruuid.h"
62
#include "fdstream.h"
E
Eric Blake 已提交
63
#include "virfile.h"
M
Martin Kletzander 已提交
64
#include "viruri.h"
65
#include "vircommand.h"
66
#include "virnodesuspend.h"
67
#include "nodeinfo.h"
68
#include "configmake.h"
69

70
#define VIR_FROM_THIS VIR_FROM_XEN
71
#define XEN_SAVE_DIR LOCALSTATEDIR "/lib/libvirt/xen/save"
72

73
static int
74
xenUnifiedNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
75
static int
76
xenUnifiedDomainGetMaxVcpus(virDomainPtr dom);
77
static int
78 79 80
xenUnifiedDomainGetVcpus(virDomainPtr dom,
                         virVcpuInfoPtr info, int maxinfo,
                         unsigned char *cpumaps, int maplen);
81

82

83
/* The five Xen drivers below us. */
D
Daniel P. Berrange 已提交
84
static struct xenUnifiedDriver const * const drivers[XEN_UNIFIED_NR_DRIVERS] = {
85 86 87 88
    [XEN_UNIFIED_HYPERVISOR_OFFSET] = &xenHypervisorDriver,
    [XEN_UNIFIED_XEND_OFFSET] = &xenDaemonDriver,
    [XEN_UNIFIED_XS_OFFSET] = &xenStoreDriver,
    [XEN_UNIFIED_XM_OFFSET] = &xenXMDriver,
89 90 91
#if WITH_XEN_INOTIFY
    [XEN_UNIFIED_INOTIFY_OFFSET] = &xenInotifyDriver,
#endif
92 93
};

94
#if defined WITH_LIBVIRTD || defined __sun
95
static bool inside_daemon = false;
96
#endif
J
John Levon 已提交
97

98 99 100 101 102
/**
 * xenNumaInit:
 * @conn: pointer to the hypervisor connection
 *
 * Initializer for previous variables. We currently assume that
R
Richard W.M. Jones 已提交
103
 * the number of physical CPU and the number of NUMA cell is fixed
104 105 106 107 108
 * until reboot which might be false in future Xen implementations.
 */
static void
xenNumaInit(virConnectPtr conn) {
    virNodeInfo nodeInfo;
D
Daniel P. Berrange 已提交
109
    xenUnifiedPrivatePtr priv;
110 111 112 113 114 115
    int ret;

    ret = xenUnifiedNodeGetInfo(conn, &nodeInfo);
    if (ret < 0)
        return;

D
Daniel P. Berrange 已提交
116
    priv = conn->privateData;
117

D
Daniel P. Berrange 已提交
118 119
    priv->nbNodeCells = nodeInfo.nodes;
    priv->nbNodeCpus = nodeInfo.cpus;
120 121
}

D
Daniel P. Berrange 已提交
122

123 124 125 126 127 128 129 130 131 132 133 134 135 136
/**
 * 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;
D
Daniel P. Berrange 已提交
137
    int ncpus;
138
    int nb_vcpu;
139
    virBitmapPtr cpulist = NULL;
140 141 142 143 144 145
    unsigned char *cpumap = NULL;
    size_t cpumaplen;
    int nb = 0;
    int n, m;
    virVcpuInfoPtr cpuinfo = NULL;
    virNodeInfo nodeinfo;
D
Daniel P. Berrange 已提交
146
    xenUnifiedPrivatePtr priv;
147 148

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

D
Daniel P. Berrange 已提交
151 152 153
    priv = dom->conn->privateData;

    if (priv->nbNodeCpus <= 0)
154
        return NULL;
155 156
    nb_vcpu = xenUnifiedDomainGetMaxVcpus(dom);
    if (nb_vcpu <= 0)
157
        return NULL;
158
    if (xenUnifiedNodeGetInfo(dom->conn, &nodeinfo) < 0)
159
        return NULL;
160

161
    if (!(cpulist = virBitmapNew(priv->nbNodeCpus))) {
162
        virReportOOMError();
163
        goto done;
164 165
    }
    if (VIR_ALLOC_N(cpuinfo, nb_vcpu) < 0) {
166
        virReportOOMError();
167
        goto done;
168
    }
169
    cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
170
    if (xalloc_oversized(nb_vcpu, cpumaplen) ||
171
        VIR_ALLOC_N(cpumap, nb_vcpu * cpumaplen) < 0) {
172
        virReportOOMError();
173
        goto done;
174
    }
175 176 177

    if ((ncpus = xenUnifiedDomainGetVcpus(dom, cpuinfo, nb_vcpu,
                                          cpumap, cpumaplen)) >= 0) {
178
        for (n = 0 ; n < ncpus ; n++) {
D
Daniel P. Berrange 已提交
179
            for (m = 0 ; m < priv->nbNodeCpus; m++) {
180 181 182
                bool used;
                ignore_value(virBitmapGetBit(cpulist, m, &used));
                if ((!used) &&
183
                    (VIR_CPU_USABLE(cpumap, cpumaplen, n, m))) {
184
                    ignore_value(virBitmapSetBit(cpulist, m));
185 186
                    nb++;
                    /* if all CPU are used just return NULL */
D
Daniel P. Berrange 已提交
187
                    if (nb == priv->nbNodeCpus)
188 189 190 191 192
                        goto done;

                }
            }
        }
193
        res = virBitmapFormat(cpulist);
194 195 196
    }

done:
197
    virBitmapFree(cpulist);
198 199
    VIR_FREE(cpumap);
    VIR_FREE(cpuinfo);
200
    return res;
201 202
}

J
John Levon 已提交
203 204 205
#ifdef WITH_LIBVIRTD

static int
206 207 208
xenInitialize(bool privileged ATTRIBUTE_UNUSED,
              virStateInhibitCallback callback ATTRIBUTE_UNUSED,
              void *opaque ATTRIBUTE_UNUSED)
J
John Levon 已提交
209
{
210
    inside_daemon = true;
J
John Levon 已提交
211 212 213 214
    return 0;
}

static virStateDriver state_driver = {
215
    .name = "Xen",
J
John Levon 已提交
216 217 218 219 220
    .initialize = xenInitialize,
};

#endif

221 222 223 224 225 226 227 228 229 230 231
/*----- 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.
 */

232
static int
233
xenUnifiedProbe(void)
234 235 236
{
#ifdef __linux__
    if (virFileExists("/proc/xen"))
237
        return 1;
238
#endif
239
#ifdef __sun
240
    int fd;
241

242 243
    if ((fd = open("/dev/xen/domcaps", O_RDONLY)) >= 0) {
        VIR_FORCE_CLOSE(fd);
244
        return 1;
245 246
    }
#endif
247
    return 0;
248 249
}

J
Jim Fehlig 已提交
250 251
#ifdef WITH_LIBXL
static int
252
xenUnifiedXendProbe(void)
J
Jim Fehlig 已提交
253 254 255 256 257 258 259 260 261 262 263 264 265 266
{
    virCommandPtr cmd;
    int status;
    int ret = 0;

    cmd = virCommandNewArgList("/usr/sbin/xend", "status", NULL);
    if (virCommandRun(cmd, &status) == 0 && status == 0)
        ret = 1;
    virCommandFree(cmd);

    return ret;
}
#endif

267 268


269
static virDrvOpenStatus
270
xenUnifiedOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags)
271
{
272
    int i, ret = VIR_DRV_OPEN_DECLINED;
273
    xenUnifiedPrivatePtr priv;
274
    char ebuf[1024];
275

J
John Levon 已提交
276 277 278 279 280 281 282 283 284
#ifdef __sun
    /*
     * Only the libvirtd instance can open this driver.
     * Everything else falls back to the remote driver.
     */
    if (!inside_daemon)
        return VIR_DRV_OPEN_DECLINED;
#endif

285 286 287 288
    if (conn->uri == NULL) {
        if (!xenUnifiedProbe())
            return VIR_DRV_OPEN_DECLINED;

289
        if (!(conn->uri = virURIParse("xen:///")))
290
            return VIR_DRV_OPEN_ERROR;
291 292 293 294 295 296 297 298 299 300 301 302
    } else {
        if (conn->uri->scheme) {
            /* Decline any scheme which isn't "xen://" or "http://". */
            if (STRCASENEQ(conn->uri->scheme, "xen") &&
                STRCASENEQ(conn->uri->scheme, "http"))
                return VIR_DRV_OPEN_DECLINED;


            /* Return an error if the path isn't '' or '/' */
            if (conn->uri->path &&
                STRNEQ(conn->uri->path, "") &&
                STRNEQ(conn->uri->path, "/")) {
303 304 305
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("unexpected Xen URI path '%s', try xen:///"),
                               conn->uri->path);
306 307
                return VIR_DRV_OPEN_ERROR;
            }
308

309 310 311 312 313 314
            /* Decline any xen:// URI with a server specified, allowing remote
             * driver to handle, but keep any http:/// URIs */
            if (STRCASEEQ(conn->uri->scheme, "xen") &&
                conn->uri->server)
                return VIR_DRV_OPEN_DECLINED;
        } else {
315
            return VIR_DRV_OPEN_DECLINED;
316 317
        }
    }
318

J
Jim Fehlig 已提交
319 320 321 322 323 324 325
#ifdef WITH_LIBXL
    /* Decline xen:// URI if xend is not running and libxenlight
     * driver is potentially available. */
    if (!xenUnifiedXendProbe())
        return VIR_DRV_OPEN_DECLINED;
#endif

326 327
    /* We now know the URI is definitely for this driver, so beyond
     * here, don't return DECLINED, always use ERROR */
328 329

    /* Allocate per-connection private data. */
330
    if (VIR_ALLOC(priv) < 0) {
331
        virReportOOMError();
332 333
        return VIR_DRV_OPEN_ERROR;
    }
D
Daniel P. Berrange 已提交
334
    if (virMutexInit(&priv->lock) < 0) {
335 336
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot initialize mutex"));
D
Daniel P. Berrange 已提交
337 338 339
        VIR_FREE(priv);
        return VIR_DRV_OPEN_ERROR;
    }
340

341
    if (!(priv->domainEvents = virDomainEventStateNew())) {
D
Daniel P. Berrange 已提交
342 343
        virMutexDestroy(&priv->lock);
        VIR_FREE(priv);
344 345
        return VIR_DRV_OPEN_ERROR;
    }
D
Daniel P. Berrange 已提交
346 347
    conn->privateData = priv;

348 349 350 351 352
    priv->handle = -1;
    priv->xendConfigVersion = -1;
    priv->xshandle = NULL;


J
John Levon 已提交
353 354
    /* Hypervisor is only run with privilege & required to succeed */
    if (xenHavePrivilege()) {
355
        VIR_DEBUG("Trying hypervisor sub-driver");
E
Eric Blake 已提交
356
        if (xenHypervisorOpen(conn, auth, flags) == VIR_DRV_OPEN_SUCCESS) {
357
            VIR_DEBUG("Activated hypervisor sub-driver");
358
            priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] = 1;
359 360
        } else {
            goto fail;
361
        }
362
    }
363

364
    /* XenD is required to succeed if privileged */
365
    VIR_DEBUG("Trying XenD sub-driver");
E
Eric Blake 已提交
366
    if (xenDaemonOpen(conn, auth, flags) == VIR_DRV_OPEN_SUCCESS) {
367
        VIR_DEBUG("Activated XenD sub-driver");
368 369 370 371
        priv->opened[XEN_UNIFIED_XEND_OFFSET] = 1;

        /* XenD is active, so try the xm & xs drivers too, both requird to
         * succeed if root, optional otherwise */
372
        if (priv->xendConfigVersion <= XEND_CONFIG_VERSION_3_0_3) {
373
            VIR_DEBUG("Trying XM sub-driver");
E
Eric Blake 已提交
374
            if (xenXMOpen(conn, auth, flags) == VIR_DRV_OPEN_SUCCESS) {
375
                VIR_DEBUG("Activated XM sub-driver");
376 377 378
                priv->opened[XEN_UNIFIED_XM_OFFSET] = 1;
            }
        }
379
        VIR_DEBUG("Trying XS sub-driver");
E
Eric Blake 已提交
380
        if (xenStoreOpen(conn, auth, flags) == VIR_DRV_OPEN_SUCCESS) {
381
            VIR_DEBUG("Activated XS sub-driver");
382 383
            priv->opened[XEN_UNIFIED_XS_OFFSET] = 1;
        } else {
J
John Levon 已提交
384 385
            if (xenHavePrivilege())
                goto fail; /* XS is mandatory when privileged */
386 387
        }
    } else {
J
John Levon 已提交
388 389
        if (xenHavePrivilege()) {
            goto fail; /* XenD is mandatory when privileged */
390
        } else {
391
            VIR_DEBUG("Handing off for remote driver");
392 393
            ret = VIR_DRV_OPEN_DECLINED; /* Let remote_driver try instead */
            goto clean;
394
        }
395 396
    }

D
Daniel P. Berrange 已提交
397 398
    xenNumaInit(conn);

399
    if (!(priv->caps = xenHypervisorMakeCapabilities(conn))) {
400
        VIR_DEBUG("Failed to make capabilities");
401 402 403
        goto fail;
    }

404
#if WITH_XEN_INOTIFY
405
    if (xenHavePrivilege()) {
406
        VIR_DEBUG("Trying Xen inotify sub-driver");
E
Eric Blake 已提交
407
        if (xenInotifyOpen(conn, auth, flags) == VIR_DRV_OPEN_SUCCESS) {
408
            VIR_DEBUG("Activated Xen inotify sub-driver");
409 410
            priv->opened[XEN_UNIFIED_INOTIFY_OFFSET] = 1;
        }
411 412 413
    }
#endif

414 415 416 417 418 419 420 421 422 423 424
    if (virAsprintf(&priv->saveDir, "%s", XEN_SAVE_DIR) == -1) {
        virReportOOMError();
        goto fail;
    }

    if (virFileMakePath(priv->saveDir) < 0) {
        VIR_ERROR(_("Failed to create save dir '%s': %s"), priv->saveDir,
                  virStrerror(errno, ebuf, sizeof(ebuf)));
        goto fail;
    }

425
    return VIR_DRV_OPEN_SUCCESS;
426

427 428 429
fail:
    ret = VIR_DRV_OPEN_ERROR;
clean:
430
    VIR_DEBUG("Failed to activate a mandatory sub-driver");
431
    for (i = 0 ; i < XEN_UNIFIED_NR_DRIVERS ; i++)
432 433
        if (priv->opened[i])
            drivers[i]->xenClose(conn);
D
Daniel P. Berrange 已提交
434
    virMutexDestroy(&priv->lock);
435
    VIR_FREE(priv->saveDir);
436
    VIR_FREE(priv);
D
Daniel P. Berrange 已提交
437
    conn->privateData = NULL;
D
Daniel Veillard 已提交
438
    return ret;
439 440
}

441 442 443
#define GET_PRIVATE(conn) \
    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) (conn)->privateData

444
static int
445
xenUnifiedClose(virConnectPtr conn)
446
{
447
    GET_PRIVATE(conn);
448
    int i;
449

450
    virCapabilitiesFree(priv->caps);
451
    virDomainEventStateFree(priv->domainEvents);
452

453
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
454 455
        if (priv->opened[i])
            drivers[i]->xenClose(conn);
456

457
    VIR_FREE(priv->saveDir);
D
Daniel P. Berrange 已提交
458 459
    virMutexDestroy(&priv->lock);
    VIR_FREE(conn->privateData);
460

461
    return 0;
462 463
}

464 465 466 467 468 469 470 471 472 473 474

#define HV_VERSION ((DOM0_INTERFACE_VERSION >> 24) * 1000000 +         \
                    ((DOM0_INTERFACE_VERSION >> 16) & 0xFF) * 1000 +   \
                    (DOM0_INTERFACE_VERSION & 0xFFFF))

unsigned long xenUnifiedVersion(void)
{
    return HV_VERSION;
}


475
static const char *
476
xenUnifiedType(virConnectPtr conn)
477
{
478
    GET_PRIVATE(conn);
479
    int i;
480

481
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
482 483
        if (priv->opened[i])
            return "Xen";
484

485
    return NULL;
486 487
}

488 489
/* Which features are supported by this driver? */
static int
490
xenUnifiedSupportsFeature(virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
491 492
{
    switch (feature) {
493 494 495 496 497
    case VIR_DRV_FEATURE_MIGRATION_V1:
    case VIR_DRV_FEATURE_MIGRATION_DIRECT:
        return 1;
    default:
        return 0;
498 499 500
    }
}

501
static int
502
xenUnifiedGetVersion(virConnectPtr conn, unsigned long *hvVer)
503
{
504
    GET_PRIVATE(conn);
505
    int i;
506

507 508
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
E
Eric Blake 已提交
509
            drivers[i]->xenVersion &&
510
            drivers[i]->xenVersion(conn, hvVer) == 0)
511
            return 0;
512

513
    return -1;
514 515
}

516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
static int
xenUnifiedIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return 0;
}

static int
xenUnifiedIsSecure(virConnectPtr conn)
{
    GET_PRIVATE(conn);
    int ret = 1;

    /* All drivers are secure, except for XenD over TCP */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET] &&
        priv->addrfamily != AF_UNIX)
        ret = 0;

    return ret;
}

536 537 538 539 540 541 542
static int
xenUnifiedIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    /* XenD reconnects for each request */
    return 1;
}

543
int
544
xenUnifiedGetMaxVcpus(virConnectPtr conn, const char *type)
545
{
546
    GET_PRIVATE(conn);
547

548
    if (type && STRCASENEQ(type, "Xen")) {
549
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
550 551
        return -1;
    }
552

553
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
554
        return xenHypervisorGetMaxVcpus(conn, type);
555
    else {
556
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
557 558
        return -1;
    }
559 560 561
}

static int
562
xenUnifiedNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
563
{
564
    GET_PRIVATE(conn);
565

566 567
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonNodeGetInfo(conn, info);
568
    return -1;
569 570 571
}

static char *
572
xenUnifiedGetCapabilities(virConnectPtr conn)
573
{
D
Daniel P. Berrange 已提交
574 575
    xenUnifiedPrivatePtr priv = conn->privateData;
    char *xml;
576

D
Daniel P. Berrange 已提交
577
    if (!(xml = virCapabilitiesFormatXML(priv->caps))) {
578
        virReportOOMError();
D
Daniel P. Berrange 已提交
579 580
        return NULL;
    }
581

D
Daniel P. Berrange 已提交
582
    return xml;
583 584 585
}

static int
586
xenUnifiedListDomains(virConnectPtr conn, int *ids, int maxids)
587
{
588
    GET_PRIVATE(conn);
589
    int ret;
590

591 592
    /* Try xenstore. */
    if (priv->opened[XEN_UNIFIED_XS_OFFSET]) {
593
        ret = xenStoreListDomains(conn, ids, maxids);
594 595
        if (ret >= 0) return ret;
    }
596

597 598
    /* Try HV. */
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
599
        ret = xenHypervisorListDomains(conn, ids, maxids);
600 601 602 603 604
        if (ret >= 0) return ret;
    }

    /* Try xend. */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
605
        ret = xenDaemonListDomains(conn, ids, maxids);
606 607 608
        if (ret >= 0) return ret;
    }

609
    return -1;
610 611 612
}

static int
613
xenUnifiedNumOfDomains(virConnectPtr conn)
614
{
615
    GET_PRIVATE(conn);
616
    int ret;
617

618 619
    /* Try xenstore. */
    if (priv->opened[XEN_UNIFIED_XS_OFFSET]) {
620
        ret = xenStoreNumOfDomains(conn);
621 622 623 624 625
        if (ret >= 0) return ret;
    }

    /* Try HV. */
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
626
        ret = xenHypervisorNumOfDomains(conn);
627 628 629 630 631
        if (ret >= 0) return ret;
    }

    /* Try xend. */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
632
        ret = xenDaemonNumOfDomains(conn);
633 634 635
        if (ret >= 0) return ret;
    }

636
    return -1;
637 638 639
}

static virDomainPtr
640 641
xenUnifiedDomainCreateXML(virConnectPtr conn,
                          const char *xmlDesc, unsigned int flags)
642
{
643
    GET_PRIVATE(conn);
644

645 646
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonCreateXML(conn, xmlDesc, flags);
647
    return NULL;
648 649
}

650 651 652 653
/* 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.
 */
654
static virDomainPtr
655
xenUnifiedDomainLookupByID(virConnectPtr conn, int id)
656
{
657
    GET_PRIVATE(conn);
658
    virDomainPtr ret;
659

660 661 662
    /* Reset any connection-level errors in virterror first, in case
     * there is one hanging around from a previous call.
     */
663
    virConnResetLastError(conn);
664

665 666
    /* Try hypervisor/xenstore combo. */
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
667
        ret = xenHypervisorLookupDomainByID(conn, id);
668 669 670 671
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }

672 673
    /* Try xend. */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
674
        ret = xenDaemonLookupByID(conn, id);
675 676 677
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }
678

679
    /* Not found. */
680
    virReportError(VIR_ERR_NO_DOMAIN, __FUNCTION__);
681
    return NULL;
682 683 684
}

static virDomainPtr
685 686
xenUnifiedDomainLookupByUUID(virConnectPtr conn,
                             const unsigned char *uuid)
687
{
688
    GET_PRIVATE(conn);
689
    virDomainPtr ret;
690

691 692 693
    /* Reset any connection-level errors in virterror first, in case
     * there is one hanging around from a previous call.
     */
694
    virConnResetLastError(conn);
695

696 697
    /* Try hypervisor/xenstore combo. */
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
698
        ret = xenHypervisorLookupDomainByUUID(conn, uuid);
699 700 701 702
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }

703 704
    /* Try xend. */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
705
        ret = xenDaemonLookupByUUID(conn, uuid);
706 707 708
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }
709

710 711
    /* Try XM for inactive domains. */
    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
712
        ret = xenXMDomainLookupByUUID(conn, uuid);
713 714 715 716 717
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }

    /* Not found. */
718
    virReportError(VIR_ERR_NO_DOMAIN, __FUNCTION__);
719
    return NULL;
720 721 722
}

static virDomainPtr
723 724
xenUnifiedDomainLookupByName(virConnectPtr conn,
                             const char *name)
725
{
726
    GET_PRIVATE(conn);
727
    virDomainPtr ret;
728

729 730 731
    /* Reset any connection-level errors in virterror first, in case
     * there is one hanging around from a previous call.
     */
732
    virConnResetLastError(conn);
733 734 735

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

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

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

755
    /* Not found. */
756
    virReportError(VIR_ERR_NO_DOMAIN, __FUNCTION__);
757
    return NULL;
758 759
}

760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778

static int
xenUnifiedDomainIsActive(virDomainPtr dom)
{
    virDomainPtr currdom;
    int ret = -1;

    /* ID field in dom may be outdated, so re-lookup */
    currdom = xenUnifiedDomainLookupByUUID(dom->conn, dom->uuid);

    if (currdom) {
        ret = currdom->id == -1 ? 0 : 1;
        virDomainFree(currdom);
    }

    return ret;
}

static int
779
xenUnifiedDomainIsPersistent(virDomainPtr dom)
780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
{
    GET_PRIVATE(dom->conn);
    virDomainPtr currdom = NULL;
    int ret = -1;

    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
        /* Old Xen, pre-inactive domain management.
         * If the XM driver can see the guest, it is definitely persistent */
        currdom = xenXMDomainLookupByUUID(dom->conn, dom->uuid);
        if (currdom)
            ret = 1;
        else
            ret = 0;
    } else {
        /* New Xen with inactive domain management */
        if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
            currdom = xenDaemonLookupByUUID(dom->conn, dom->uuid);
            if (currdom) {
                if (currdom->id == -1) {
                    /* If its inactive, then trivially, it must be persistent */
                    ret = 1;
                } else {
                    char *path;
                    char uuidstr[VIR_UUID_STRING_BUFLEN];

                    /* If its running there's no official way to tell, so we
                     * go behind xend's back & look at the config dir */

                    virUUIDFormat(dom->uuid, uuidstr);
                    if (virAsprintf(&path, "%s/%s", XEND_DOMAINS_DIR, uuidstr) < 0) {
810
                        virReportOOMError();
811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
                        goto done;
                    }
                    if (access(path, R_OK) == 0)
                        ret = 1;
                    else if (errno == ENOENT)
                        ret = 0;
                }
            }
        }
    }

done:
    if (currdom)
        virDomainFree(currdom);

    return ret;
}

829 830 831 832 833 834
static int
xenUnifiedDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
{
    return 0;
}

835
static int
836
xenUnifiedDomainSuspend(virDomainPtr dom)
837
{
838
    GET_PRIVATE(dom->conn);
839
    int i;
840

841 842 843
    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
844
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
845
        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
846
            priv->opened[i] &&
E
Eric Blake 已提交
847
            drivers[i]->xenDomainSuspend &&
848
            drivers[i]->xenDomainSuspend(dom) == 0)
849
            return 0;
850

851
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
E
Eric Blake 已提交
852
        xenHypervisorPauseDomain(dom) == 0)
853
        return 0;
854

855
    return -1;
856 857 858
}

static int
859
xenUnifiedDomainResume(virDomainPtr dom)
860
{
861
    GET_PRIVATE(dom->conn);
862
    int i;
863

864 865 866
    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
867
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
868
        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
869
            priv->opened[i] &&
E
Eric Blake 已提交
870
            drivers[i]->xenDomainResume &&
871
            drivers[i]->xenDomainResume(dom) == 0)
872
            return 0;
873

874
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
E
Eric Blake 已提交
875
        xenHypervisorResumeDomain(dom) == 0)
876
        return 0;
877

878
    return -1;
879 880 881
}

static int
882 883
xenUnifiedDomainShutdownFlags(virDomainPtr dom,
                              unsigned int flags)
884
{
885
    GET_PRIVATE(dom->conn);
886
    int i;
887

888 889
    virCheckFlags(0, -1);

890 891
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
E
Eric Blake 已提交
892
            drivers[i]->xenDomainShutdown &&
893
            drivers[i]->xenDomainShutdown(dom) == 0)
894
            return 0;
895

896
    return -1;
897 898
}

899 900 901 902 903 904
static int
xenUnifiedDomainShutdown(virDomainPtr dom)
{
    return xenUnifiedDomainShutdownFlags(dom, 0);
}

905
static int
906
xenUnifiedDomainReboot(virDomainPtr dom, unsigned int flags)
907
{
908
    GET_PRIVATE(dom->conn);
909
    int i;
910

911 912
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
E
Eric Blake 已提交
913
            drivers[i]->xenDomainReboot &&
914
            drivers[i]->xenDomainReboot(dom, flags) == 0)
915
            return 0;
916

917
    return -1;
918 919
}

920 921 922 923 924 925 926 927 928 929 930 931 932 933 934
static int
xenUnifiedDomainDestroyFlags(virDomainPtr dom,
                             unsigned int flags)
{
    GET_PRIVATE(dom->conn);
    int i;

    virCheckFlags(0, -1);

    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
            priv->opened[i] &&
E
Eric Blake 已提交
935 936
            drivers[i]->xenDomainDestroyFlags &&
            drivers[i]->xenDomainDestroyFlags(dom, flags) == 0)
937 938 939
            return 0;

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
E
Eric Blake 已提交
940
        xenHypervisorDestroyDomainFlags(dom, flags) == 0)
941 942 943 944 945
        return 0;

    return -1;
}

946 947 948 949 950 951
static int
xenUnifiedDomainDestroy(virDomainPtr dom)
{
    return xenUnifiedDomainDestroyFlags(dom, 0);
}

952
static char *
953
xenUnifiedDomainGetOSType(virDomainPtr dom)
954
{
955
    GET_PRIVATE(dom->conn);
956 957
    int i;
    char *ret;
958

959
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
960
        if (priv->opened[i] && drivers[i]->xenDomainGetOSType) {
961
            ret = drivers[i]->xenDomainGetOSType(dom);
962 963
            if (ret) return ret;
        }
964

965
    return NULL;
966 967
}

968
static unsigned long long
969
xenUnifiedDomainGetMaxMemory(virDomainPtr dom)
970
{
971
    GET_PRIVATE(dom->conn);
972
    int i;
973
    unsigned long long ret;
974

975
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
976
        if (priv->opened[i] && drivers[i]->xenDomainGetMaxMemory) {
977
            ret = drivers[i]->xenDomainGetMaxMemory(dom);
978 979
            if (ret != 0) return ret;
        }
980

981
    return 0;
982 983 984
}

static int
985
xenUnifiedDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
986
{
987
    GET_PRIVATE(dom->conn);
988
    int i;
989

990 991
    /* Prefer xend for setting max memory */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
992
        if (xenDaemonDomainSetMaxMemory(dom, memory) == 0)
993 994 995
            return 0;
    }

996
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
997 998
        if (i != XEN_UNIFIED_XEND_OFFSET &&
            priv->opened[i] &&
E
Eric Blake 已提交
999
            drivers[i]->xenDomainSetMaxMemory &&
1000
            drivers[i]->xenDomainSetMaxMemory(dom, memory) == 0)
1001
            return 0;
1002

1003
    return -1;
1004 1005 1006
}

static int
1007
xenUnifiedDomainSetMemory(virDomainPtr dom, unsigned long memory)
1008
{
1009
    GET_PRIVATE(dom->conn);
1010
    int i;
1011

1012 1013
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
E
Eric Blake 已提交
1014
            drivers[i]->xenDomainSetMemory &&
1015
            drivers[i]->xenDomainSetMemory(dom, memory) == 0)
1016
            return 0;
1017

1018
    return -1;
1019 1020 1021
}

static int
1022
xenUnifiedDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
1023
{
1024
    GET_PRIVATE(dom->conn);
1025
    int i;
1026

1027 1028
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
E
Eric Blake 已提交
1029
            drivers[i]->xenDomainGetInfo &&
1030
            drivers[i]->xenDomainGetInfo(dom, info) == 0)
1031
            return 0;
1032

1033
    return -1;
1034 1035
}

1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076
static int
xenUnifiedDomainGetState(virDomainPtr dom,
                         int *state,
                         int *reason,
                         unsigned int flags)
{
    GET_PRIVATE(dom->conn);
    int ret;

    virCheckFlags(0, -1);

    /* trying drivers in the same order as GetInfo for consistent results:
     * hypervisor, xend, xs, and xm */

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
        ret = xenHypervisorGetDomainState(dom, state, reason, flags);
        if (ret >= 0)
            return ret;
    }

    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
        ret = xenDaemonDomainGetState(dom, state, reason, flags);
        if (ret >= 0)
            return ret;
    }

    if (priv->opened[XEN_UNIFIED_XS_OFFSET]) {
        ret = xenStoreDomainGetState(dom, state, reason, flags);
        if (ret >= 0)
            return ret;
    }

    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
        ret = xenXMDomainGetState(dom, state, reason, flags);
        if (ret >= 0)
            return ret;
    }

    return -1;
}

1077
static int
1078 1079
xenUnifiedDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml,
                          unsigned int flags)
1080
{
1081
    GET_PRIVATE(dom->conn);
1082

1083 1084
    virCheckFlags(0, -1);
    if (dxml) {
1085 1086
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1087 1088 1089
        return -1;
    }

1090 1091
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonDomainSave(dom, to);
1092
    return -1;
1093 1094 1095
}

static int
1096 1097 1098 1099 1100
xenUnifiedDomainSave(virDomainPtr dom, const char *to)
{
    return xenUnifiedDomainSaveFlags(dom, to, NULL, 0);
}

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 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 1164 1165 1166 1167 1168 1169 1170 1171
static char *
xenUnifiedDomainManagedSavePath(xenUnifiedPrivatePtr priv, virDomainPtr dom)
{
    char *ret;

    if (virAsprintf(&ret, "%s/%s.save", priv->saveDir, dom->name) < 0) {
        virReportOOMError();
        return NULL;
    }

    VIR_DEBUG("managed save image: %s", ret);
    return ret;
}

static int
xenUnifiedDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
    GET_PRIVATE(dom->conn);
    char *name;
    int ret = -1;

    virCheckFlags(0, -1);

    name = xenUnifiedDomainManagedSavePath(priv, dom);
    if (!name)
        goto cleanup;

    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        ret = xenDaemonDomainSave(dom, name);

cleanup:
    VIR_FREE(name);
    return ret;
}

static int
xenUnifiedDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    GET_PRIVATE(dom->conn);
    char *name;
    int ret = -1;

    virCheckFlags(0, -1);

    name = xenUnifiedDomainManagedSavePath(priv, dom);
    if (!name)
        return ret;

    ret = virFileExists(name);
    VIR_FREE(name);
    return ret;
}

static int
xenUnifiedDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
{
    GET_PRIVATE(dom->conn);
    char *name;
    int ret = -1;

    virCheckFlags(0, -1);

    name = xenUnifiedDomainManagedSavePath(priv, dom);
    if (!name)
        return ret;

    ret = unlink(name);
    VIR_FREE(name);
    return ret;
}

1172 1173 1174
static int
xenUnifiedDomainRestoreFlags(virConnectPtr conn, const char *from,
                             const char *dxml, unsigned int flags)
1175
{
1176
    GET_PRIVATE(conn);
1177

1178 1179
    virCheckFlags(0, -1);
    if (dxml) {
1180 1181
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1182 1183 1184
        return -1;
    }

1185 1186
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonDomainRestore(conn, from);
1187
    return -1;
1188 1189
}

1190
static int
1191
xenUnifiedDomainRestore(virConnectPtr conn, const char *from)
1192 1193 1194 1195
{
    return xenUnifiedDomainRestoreFlags(conn, from, NULL, 0);
}

1196
static int
1197
xenUnifiedDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
1198
{
1199
    GET_PRIVATE(dom->conn);
1200

1201 1202
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonDomainCoreDump(dom, to, flags);
1203
    return -1;
1204 1205 1206
}

static int
1207 1208
xenUnifiedDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
                              unsigned int flags)
1209
{
1210
    GET_PRIVATE(dom->conn);
1211
    int ret;
1212

1213 1214 1215 1216 1217 1218 1219 1220 1221
    virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
                  VIR_DOMAIN_VCPU_CONFIG |
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

    /* At least one of LIVE or CONFIG must be set.  MAXIMUM cannot be
     * mixed with LIVE.  */
    if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0 ||
        (flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) ==
         (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) {
1222 1223
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
1224 1225 1226
        return -1;
    }
    if (!nvcpus || (unsigned short) nvcpus != nvcpus) {
1227 1228
        virReportError(VIR_ERR_INVALID_ARG,
                       _("argument out of range: %d"), nvcpus);
1229 1230 1231
        return -1;
    }

1232 1233 1234
    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
        ret = xenDaemonDomainSetVcpusFlags(dom, nvcpus, flags);
        if (ret != -2)
            return ret;
    }
    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
        ret = xenXMDomainSetVcpusFlags(dom, nvcpus, flags);
        if (ret != -2)
            return ret;
    }
    if (flags == VIR_DOMAIN_VCPU_LIVE)
        return xenHypervisorSetVcpus(dom, nvcpus);
1247

1248
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1249
    return -1;
1250 1251
}

1252
static int
1253
xenUnifiedDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
1254
{
1255 1256 1257 1258 1259 1260
    unsigned int flags = VIR_DOMAIN_VCPU_LIVE;

    /* Per the documented API, it is hypervisor-dependent whether this
     * affects just _LIVE or _LIVE|_CONFIG; in xen's case, that
     * depends on xendConfigVersion.  */
    if (dom) {
1261
        GET_PRIVATE(dom->conn);
1262
        if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
1263
            flags |= VIR_DOMAIN_VCPU_CONFIG;
1264
        return xenUnifiedDomainSetVcpusFlags(dom, nvcpus, flags);
1265
    }
1266
    return -1;
1267 1268
}

1269
static int
1270 1271
xenUnifiedDomainPinVcpu(virDomainPtr dom, unsigned int vcpu,
                        unsigned char *cpumap, int maplen)
1272
{
1273
    GET_PRIVATE(dom->conn);
1274
    int i;
1275

1276 1277
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
E
Eric Blake 已提交
1278
            drivers[i]->xenDomainPinVcpu &&
1279
            drivers[i]->xenDomainPinVcpu(dom, vcpu, cpumap, maplen) == 0)
1280
            return 0;
1281

1282
    return -1;
1283 1284 1285
}

static int
1286 1287 1288
xenUnifiedDomainGetVcpus(virDomainPtr dom,
                         virVcpuInfoPtr info, int maxinfo,
                         unsigned char *cpumaps, int maplen)
1289
{
1290
    GET_PRIVATE(dom->conn);
1291
    int i, ret;
1292

1293
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
1294
        if (priv->opened[i] && drivers[i]->xenDomainGetVcpus) {
1295
            ret = drivers[i]->xenDomainGetVcpus(dom, info, maxinfo, cpumaps, maplen);
1296 1297 1298
            if (ret > 0)
                return ret;
        }
1299
    return -1;
1300 1301 1302
}

static int
1303
xenUnifiedDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
1304
{
1305
    GET_PRIVATE(dom->conn);
1306
    int ret;
1307

1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323
    virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
                  VIR_DOMAIN_VCPU_CONFIG |
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
        ret = xenDaemonDomainGetVcpusFlags(dom, flags);
        if (ret != -2)
            return ret;
    }
    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
        ret = xenXMDomainGetVcpusFlags(dom, flags);
        if (ret != -2)
            return ret;
    }
    if (flags == (VIR_DOMAIN_VCPU_CONFIG | VIR_DOMAIN_VCPU_MAXIMUM))
        return xenHypervisorGetVcpuMax(dom);
1324

1325
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1326
    return -1;
1327 1328
}

1329
static int
1330
xenUnifiedDomainGetMaxVcpus(virDomainPtr dom)
1331 1332 1333 1334 1335
{
    return xenUnifiedDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
                                               VIR_DOMAIN_VCPU_MAXIMUM));
}

1336
static char *
1337
xenUnifiedDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
1338
{
1339
    GET_PRIVATE(dom->conn);
1340

1341
    if (dom->id == -1 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
1342
        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
1343
            return xenXMDomainGetXMLDesc(dom, flags);
1344 1345 1346
    } else {
        if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
            char *cpus, *res;
D
Daniel P. Berrange 已提交
1347
            xenUnifiedLock(priv);
1348
            cpus = xenDomainUsedCpus(dom);
D
Daniel P. Berrange 已提交
1349
            xenUnifiedUnlock(priv);
1350
            res = xenDaemonDomainGetXMLDesc(dom, flags, cpus);
1351
            VIR_FREE(cpus);
1352
            return res;
1353
        }
1354
    }
1355

1356
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1357
    return NULL;
1358 1359
}

1360 1361 1362 1363 1364

static char *
xenUnifiedDomainXMLFromNative(virConnectPtr conn,
                              const char *format,
                              const char *config,
E
Eric Blake 已提交
1365
                              unsigned int flags)
1366 1367 1368 1369
{
    virDomainDefPtr def = NULL;
    char *ret = NULL;
    virConfPtr conf = NULL;
1370 1371 1372
    int id;
    char * tty;
    int vncport;
1373 1374
    GET_PRIVATE(conn);

E
Eric Blake 已提交
1375 1376
    virCheckFlags(0, NULL);

1377 1378
    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
1379 1380
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), format);
1381 1382 1383 1384
        return NULL;
    }

    if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
1385
        conf = virConfReadMem(config, strlen(config), 0);
1386 1387 1388
        if (!conf)
            goto cleanup;

M
Markus Groß 已提交
1389
        def = xenParseXM(conf, priv->xendConfigVersion, priv->caps);
1390
    } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
1391 1392 1393 1394 1395
        id = xenGetDomIdFromSxprString(config, priv->xendConfigVersion);
        xenUnifiedLock(priv);
        tty = xenStoreDomainGetConsolePath(conn, id);
        vncport = xenStoreDomainGetVNCPort(conn, id);
        xenUnifiedUnlock(priv);
M
Markus Groß 已提交
1396
        def = xenParseSxprString(config, priv->xendConfigVersion, tty,
1397
                                       vncport);
1398 1399 1400 1401
    }
    if (!def)
        goto cleanup;

1402
    ret = virDomainDefFormat(def, 0);
1403 1404 1405

cleanup:
    virDomainDefFree(def);
1406 1407
    if (conf)
        virConfFree(conf);
1408 1409 1410 1411 1412 1413 1414 1415 1416
    return ret;
}


#define MAX_CONFIG_SIZE (1024 * 65)
static char *
xenUnifiedDomainXMLToNative(virConnectPtr conn,
                            const char *format,
                            const char *xmlData,
E
Eric Blake 已提交
1417
                            unsigned int flags)
1418 1419 1420 1421 1422 1423
{
    virDomainDefPtr def = NULL;
    char *ret = NULL;
    virConfPtr conf = NULL;
    GET_PRIVATE(conn);

E
Eric Blake 已提交
1424 1425
    virCheckFlags(0, NULL);

1426 1427
    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
1428 1429
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), format);
1430 1431 1432
        goto cleanup;
    }

M
Matthias Bolte 已提交
1433 1434
    if (!(def = virDomainDefParseString(priv->caps, xmlData,
                                        1 << VIR_DOMAIN_VIRT_XEN, 0)))
1435 1436 1437 1438
        goto cleanup;

    if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
        int len = MAX_CONFIG_SIZE;
M
Markus Groß 已提交
1439
        conf = xenFormatXM(conn, def, priv->xendConfigVersion);
1440 1441 1442 1443
        if (!conf)
            goto cleanup;

        if (VIR_ALLOC_N(ret, len) < 0) {
1444
            virReportOOMError();
1445 1446 1447 1448 1449 1450 1451 1452
            goto cleanup;
        }

        if (virConfWriteMem(ret, &len, conf) < 0) {
            VIR_FREE(ret);
            goto cleanup;
        }
    } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
M
Markus Groß 已提交
1453
        ret = xenFormatSxpr(conn, def, priv->xendConfigVersion);
1454 1455 1456 1457 1458 1459 1460 1461 1462 1463
    }

cleanup:
    virDomainDefFree(def);
    if (conf)
        virConfFree(conf);
    return ret;
}


1464
static int
1465 1466 1467 1468 1469 1470 1471 1472
xenUnifiedDomainMigratePrepare(virConnectPtr dconn,
                               char **cookie,
                               int *cookielen,
                               const char *uri_in,
                               char **uri_out,
                               unsigned long flags,
                               const char *dname,
                               unsigned long resource)
1473 1474 1475
{
    GET_PRIVATE(dconn);

E
Eric Blake 已提交
1476 1477
    virCheckFlags(XEN_MIGRATION_FLAGS, -1);

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

1483
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1484 1485 1486 1487
    return -1;
}

static int
1488 1489 1490 1491 1492 1493 1494
xenUnifiedDomainMigratePerform(virDomainPtr dom,
                               const char *cookie,
                               int cookielen,
                               const char *uri,
                               unsigned long flags,
                               const char *dname,
                               unsigned long resource)
1495 1496 1497
{
    GET_PRIVATE(dom->conn);

E
Eric Blake 已提交
1498 1499
    virCheckFlags(XEN_MIGRATION_FLAGS, -1);

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

1504
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1505 1506 1507 1508
    return -1;
}

static virDomainPtr
1509 1510 1511 1512 1513 1514
xenUnifiedDomainMigrateFinish(virConnectPtr dconn,
                              const char *dname,
                              const char *cookie ATTRIBUTE_UNUSED,
                              int cookielen ATTRIBUTE_UNUSED,
                              const char *uri ATTRIBUTE_UNUSED,
                              unsigned long flags)
1515
{
1516 1517 1518 1519
    virDomainPtr dom = NULL;
    char *domain_xml = NULL;
    virDomainPtr dom_new = NULL;

E
Eric Blake 已提交
1520 1521
    virCheckFlags(XEN_MIGRATION_FLAGS, NULL);

1522
    dom = xenUnifiedDomainLookupByName(dconn, dname);
1523 1524 1525 1526 1527
    if (! dom) {
        return NULL;
    }

    if (flags & VIR_MIGRATE_PERSIST_DEST) {
1528
        domain_xml = xenDaemonDomainGetXMLDesc(dom, 0, NULL);
1529
        if (! domain_xml) {
1530 1531
            virReportError(VIR_ERR_MIGRATE_PERSIST_FAILED,
                           "%s", _("failed to get XML representation of migrated domain"));
1532 1533 1534
            goto failure;
        }

1535
        dom_new = xenDaemonDomainDefineXML(dconn, domain_xml);
1536
        if (! dom_new) {
1537 1538
            virReportError(VIR_ERR_MIGRATE_PERSIST_FAILED,
                           "%s", _("failed to define domain on destination host"));
1539 1540 1541 1542
            goto failure;
        }

        /* Free additional reference added by Define */
1543
        virDomainFree(dom_new);
1544 1545
    }

1546
    VIR_FREE(domain_xml);
1547 1548 1549 1550 1551

    return dom;


failure:
1552
    virDomainFree(dom);
1553

1554
    VIR_FREE(domain_xml);
1555 1556

    return NULL;
1557 1558
}

1559
static int
1560 1561
xenUnifiedListDefinedDomains(virConnectPtr conn, char **const names,
                             int maxnames)
1562
{
1563
    GET_PRIVATE(conn);
1564 1565
    int i;
    int ret;
1566

1567
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
1568
        if (priv->opened[i] && drivers[i]->xenListDefinedDomains) {
1569
            ret = drivers[i]->xenListDefinedDomains(conn, names, maxnames);
1570 1571
            if (ret >= 0) return ret;
        }
1572

1573
    return -1;
1574 1575 1576
}

static int
1577
xenUnifiedNumOfDefinedDomains(virConnectPtr conn)
1578
{
1579
    GET_PRIVATE(conn);
1580 1581
    int i;
    int ret;
1582

1583
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
1584
        if (priv->opened[i] && drivers[i]->xenNumOfDefinedDomains) {
1585
            ret = drivers[i]->xenNumOfDefinedDomains(conn);
1586 1587
            if (ret >= 0) return ret;
        }
1588

1589
    return -1;
1590 1591 1592
}

static int
1593
xenUnifiedDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
1594
{
1595
    GET_PRIVATE(dom->conn);
1596
    int i;
1597 1598
    int ret = -1;
    char *name = NULL;
1599

1600 1601
    virCheckFlags(0, -1);

1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615
    name = xenUnifiedDomainManagedSavePath(priv, dom);
    if (!name)
        goto cleanup;

    if (virFileExists(name)) {
        if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
            ret = xenDaemonDomainRestore(dom->conn, name);
            if (ret == 0)
                unlink(name);
        }
        goto cleanup;
    }

    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) {
E
Eric Blake 已提交
1616
        if (priv->opened[i] && drivers[i]->xenDomainCreate &&
1617 1618 1619 1620 1621
            drivers[i]->xenDomainCreate(dom) == 0) {
            ret = 0;
            goto cleanup;
        }
    }
1622

1623 1624 1625
cleanup:
    VIR_FREE(name);
    return ret;
1626 1627
}

1628
static int
1629
xenUnifiedDomainCreate(virDomainPtr dom)
1630 1631 1632 1633
{
    return xenUnifiedDomainCreateWithFlags(dom, 0);
}

1634
static virDomainPtr
1635
xenUnifiedDomainDefineXML(virConnectPtr conn, const char *xml)
1636
{
1637
    GET_PRIVATE(conn);
1638 1639
    int i;
    virDomainPtr ret;
1640

1641
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
1642
        if (priv->opened[i] && drivers[i]->xenDomainDefineXML) {
1643
            ret = drivers[i]->xenDomainDefineXML(conn, xml);
1644 1645
            if (ret) return ret;
        }
1646

1647
    return NULL;
1648 1649 1650
}

static int
1651
xenUnifiedDomainUndefineFlags(virDomainPtr dom, unsigned int flags)
1652
{
1653
    GET_PRIVATE(dom->conn);
1654
    int i;
1655

1656
    virCheckFlags(0, -1);
1657
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
1658
        if (priv->opened[i] && drivers[i]->xenDomainUndefine &&
1659
            drivers[i]->xenDomainUndefine(dom) == 0)
1660
            return 0;
1661

1662
    return -1;
1663 1664
}

1665
static int
1666
xenUnifiedDomainUndefine(virDomainPtr dom) {
1667 1668 1669
    return xenUnifiedDomainUndefineFlags(dom, 0);
}

1670
static int
1671
xenUnifiedDomainAttachDevice(virDomainPtr dom, const char *xml)
1672 1673 1674
{
    GET_PRIVATE(dom->conn);
    int i;
1675
    unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
1676

1677 1678 1679 1680 1681 1682
    /*
     * HACK: xend with xendConfigVersion >= 3 does not support changing live
     * config without touching persistent config, we add the extra flag here
     * to make this API work
     */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET] &&
1683
        priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
1684
        flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
1685 1686

    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
1687 1688
        if (priv->opened[i] && drivers[i]->xenDomainAttachDeviceFlags &&
            drivers[i]->xenDomainAttachDeviceFlags(dom, xml, flags) == 0)
1689 1690 1691 1692 1693 1694
            return 0;

    return -1;
}

static int
1695 1696
xenUnifiedDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
1697
{
1698
    GET_PRIVATE(dom->conn);
1699
    int i;
1700

1701
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
1702 1703
        if (priv->opened[i] && drivers[i]->xenDomainAttachDeviceFlags &&
            drivers[i]->xenDomainAttachDeviceFlags(dom, xml, flags) == 0)
1704
            return 0;
1705

1706
    return -1;
1707 1708 1709
}

static int
1710
xenUnifiedDomainDetachDevice(virDomainPtr dom, const char *xml)
1711 1712 1713
{
    GET_PRIVATE(dom->conn);
    int i;
1714
    unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
1715

1716 1717 1718 1719 1720 1721
    /*
     * HACK: xend with xendConfigVersion >= 3 does not support changing live
     * config without touching persistent config, we add the extra flag here
     * to make this API work
     */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET] &&
1722
        priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
1723
        flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
1724 1725

    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
1726 1727
        if (priv->opened[i] && drivers[i]->xenDomainDetachDeviceFlags &&
            drivers[i]->xenDomainDetachDeviceFlags(dom, xml, flags) == 0)
1728 1729 1730 1731 1732 1733
            return 0;

    return -1;
}

static int
1734 1735
xenUnifiedDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
1736
{
1737
    GET_PRIVATE(dom->conn);
1738
    int i;
1739

1740
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
1741 1742
        if (priv->opened[i] && drivers[i]->xenDomainDetachDeviceFlags &&
            drivers[i]->xenDomainDetachDeviceFlags(dom, xml, flags) == 0)
1743
            return 0;
1744

1745
    return -1;
1746 1747
}

1748
static int
1749 1750
xenUnifiedDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
1751 1752 1753
{
    GET_PRIVATE(dom->conn);

1754 1755
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonUpdateDeviceFlags(dom, xml, flags);
1756 1757 1758
    return -1;
}

1759
static int
1760
xenUnifiedDomainGetAutostart(virDomainPtr dom, int *autostart)
1761 1762 1763
{
    GET_PRIVATE(dom->conn);

1764
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
1765 1766 1767 1768 1769 1770
        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
            return xenXMDomainGetAutostart(dom, autostart);
    } else {
        if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
            return xenDaemonDomainGetAutostart(dom, autostart);
    }
1771

1772
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1773 1774 1775 1776
    return -1;
}

static int
1777
xenUnifiedDomainSetAutostart(virDomainPtr dom, int autostart)
1778 1779 1780
{
    GET_PRIVATE(dom->conn);

1781
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
1782 1783 1784 1785 1786 1787
        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
            return xenXMDomainSetAutostart(dom, autostart);
    } else {
        if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
            return xenDaemonDomainSetAutostart(dom, autostart);
    }
1788

1789
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1790 1791 1792
    return -1;
}

1793
static char *
1794
xenUnifiedDomainGetSchedulerType(virDomainPtr dom, int *nparams)
1795 1796 1797 1798 1799 1800
{
    GET_PRIVATE(dom->conn);
    int i;
    char *schedulertype;

    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; i++) {
E
Eric Blake 已提交
1801
        if (priv->opened[i] && drivers[i]->xenDomainGetSchedulerType) {
1802
            schedulertype = drivers[i]->xenDomainGetSchedulerType(dom, nparams);
1803
            if (schedulertype != NULL)
1804
                return schedulertype;
1805 1806
        }
    }
1807
    return NULL;
1808 1809 1810
}

static int
1811 1812 1813 1814
xenUnifiedDomainGetSchedulerParametersFlags(virDomainPtr dom,
                                            virTypedParameterPtr params,
                                            int *nparams,
                                            unsigned int flags)
1815 1816 1817 1818
{
    GET_PRIVATE(dom->conn);
    int i, ret;

1819 1820
    virCheckFlags(0, -1);

1821
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) {
E
Eric Blake 已提交
1822 1823
        if (priv->opened[i] && drivers[i]->xenDomainGetSchedulerParameters) {
           ret = drivers[i]->xenDomainGetSchedulerParameters(dom, params, nparams);
1824
           if (ret == 0)
1825
               return 0;
1826
        }
1827
    }
1828
    return -1;
1829 1830 1831
}

static int
1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844
xenUnifiedDomainGetSchedulerParameters(virDomainPtr dom,
                                       virTypedParameterPtr params,
                                       int *nparams)
{
    return xenUnifiedDomainGetSchedulerParametersFlags(dom, params,
                                                       nparams, 0);
}

static int
xenUnifiedDomainSetSchedulerParametersFlags(virDomainPtr dom,
                                            virTypedParameterPtr params,
                                            int nparams,
                                            unsigned int flags)
1845 1846 1847 1848
{
    GET_PRIVATE(dom->conn);
    int i, ret;

1849 1850
    virCheckFlags(0, -1);

1851 1852
    /* do the hypervisor call last to get better error */
    for (i = XEN_UNIFIED_NR_DRIVERS - 1; i >= 0; i--) {
E
Eric Blake 已提交
1853 1854
        if (priv->opened[i] && drivers[i]->xenDomainSetSchedulerParameters) {
           ret = drivers[i]->xenDomainSetSchedulerParameters(dom, params, nparams);
1855 1856 1857
           if (ret == 0)
               return 0;
        }
1858 1859
    }

1860
    return -1;
1861 1862
}

1863 1864 1865 1866 1867 1868 1869 1870 1871
static int
xenUnifiedDomainSetSchedulerParameters(virDomainPtr dom,
                                       virTypedParameterPtr params,
                                       int nparams)
{
    return xenUnifiedDomainSetSchedulerParametersFlags(dom, params,
                                                       nparams, 0);
}

1872
static int
1873 1874
xenUnifiedDomainBlockStats(virDomainPtr dom, const char *path,
                           struct _virDomainBlockStats *stats)
1875
{
1876
    GET_PRIVATE(dom->conn);
1877 1878

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

1881
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1882 1883 1884 1885
    return -1;
}

static int
1886 1887
xenUnifiedDomainInterfaceStats(virDomainPtr dom, const char *path,
                               struct _virDomainInterfaceStats *stats)
1888
{
1889
    GET_PRIVATE(dom->conn);
1890 1891

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

1894
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1895 1896 1897
    return -1;
}

R
Richard W.M. Jones 已提交
1898
static int
1899 1900 1901
xenUnifiedDomainBlockPeek(virDomainPtr dom, const char *path,
                          unsigned long long offset, size_t size,
                          void *buffer, unsigned int flags)
R
Richard W.M. Jones 已提交
1902 1903
{
    int r;
1904
    GET_PRIVATE(dom->conn);
R
Richard W.M. Jones 已提交
1905

E
Eric Blake 已提交
1906 1907
    virCheckFlags(0, -1);

R
Richard W.M. Jones 已提交
1908
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
1909
        r = xenDaemonDomainBlockPeek(dom, path, offset, size, buffer);
R
Richard W.M. Jones 已提交
1910 1911 1912 1913 1914
        if (r != -2) return r;
        /* r == -2 means declined, so fall through to XM driver ... */
    }

    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
1915
        if (xenXMDomainBlockPeek(dom, path, offset, size, buffer) == 0)
R
Richard W.M. Jones 已提交
1916 1917 1918
            return 0;
    }

1919
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
R
Richard W.M. Jones 已提交
1920 1921 1922
    return -1;
}

1923
static int
1924 1925
xenUnifiedNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems,
                                 int startCell, int maxCells)
1926
{
1927
    GET_PRIVATE(conn);
1928 1929

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

1933
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1934 1935 1936
    return -1;
}

1937
static unsigned long long
1938
xenUnifiedNodeGetFreeMemory(virConnectPtr conn)
1939 1940 1941
{
    unsigned long long freeMem = 0;
    int ret;
1942
    GET_PRIVATE(conn);
1943 1944

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
1945 1946
        ret = xenHypervisorNodeGetCellsFreeMemory(conn, &freeMem,
                                                  -1, 1);
1947
        if (ret != 1)
1948 1949
            return 0;
        return freeMem;
1950 1951
    }

1952
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1953
    return 0;
1954 1955
}

1956

1957
static int
1958 1959 1960 1961
xenUnifiedDomainEventRegister(virConnectPtr conn,
                              virConnectDomainEventCallback callback,
                              void *opaque,
                              virFreeCallback freefunc)
1962
{
1963
    GET_PRIVATE(conn);
D
Daniel P. Berrange 已提交
1964

1965
    int ret;
D
Daniel P. Berrange 已提交
1966
    xenUnifiedLock(priv);
1967

1968
    if (priv->xsWatch == -1) {
1969
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
D
Daniel P. Berrange 已提交
1970
        xenUnifiedUnlock(priv);
1971 1972 1973
        return -1;
    }

1974 1975
    ret = virDomainEventStateRegister(conn, priv->domainEvents,
                                      callback, opaque, freefunc);
1976

D
Daniel P. Berrange 已提交
1977
    xenUnifiedUnlock(priv);
1978
    return ret;
1979 1980
}

1981

1982
static int
1983 1984
xenUnifiedDomainEventDeregister(virConnectPtr conn,
                                virConnectDomainEventCallback callback)
1985 1986
{
    int ret;
1987
    GET_PRIVATE(conn);
D
Daniel P. Berrange 已提交
1988 1989
    xenUnifiedLock(priv);

1990
    if (priv->xsWatch == -1) {
1991
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
D
Daniel P. Berrange 已提交
1992
        xenUnifiedUnlock(priv);
1993 1994 1995
        return -1;
    }

1996 1997 1998
    ret = virDomainEventStateDeregister(conn,
                                        priv->domainEvents,
                                        callback);
1999

D
Daniel P. Berrange 已提交
2000
    xenUnifiedUnlock(priv);
2001 2002 2003
    return ret;
}

2004

2005 2006 2007 2008 2009 2010 2011 2012
static int
xenUnifiedDomainEventRegisterAny(virConnectPtr conn,
                                 virDomainPtr dom,
                                 int eventID,
                                 virConnectDomainEventGenericCallback callback,
                                 void *opaque,
                                 virFreeCallback freefunc)
{
2013
    GET_PRIVATE(conn);
2014 2015 2016 2017 2018

    int ret;
    xenUnifiedLock(priv);

    if (priv->xsWatch == -1) {
2019
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
2020 2021 2022 2023
        xenUnifiedUnlock(priv);
        return -1;
    }

2024 2025 2026
    if (virDomainEventStateRegisterID(conn, priv->domainEvents,
                                      dom, eventID,
                                      callback, opaque, freefunc, &ret) < 0)
2027
        ret = -1;
2028 2029

    xenUnifiedUnlock(priv);
2030
    return ret;
2031 2032 2033 2034 2035 2036 2037
}

static int
xenUnifiedDomainEventDeregisterAny(virConnectPtr conn,
                                   int callbackID)
{
    int ret;
2038
    GET_PRIVATE(conn);
2039 2040 2041
    xenUnifiedLock(priv);

    if (priv->xsWatch == -1) {
2042
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
2043 2044 2045 2046
        xenUnifiedUnlock(priv);
        return -1;
    }

2047 2048 2049
    ret = virDomainEventStateDeregisterID(conn,
                                          priv->domainEvents,
                                          callbackID);
2050 2051 2052 2053 2054 2055

    xenUnifiedUnlock(priv);
    return ret;
}


2056
static int
2057 2058 2059 2060 2061
xenUnifiedNodeDeviceGetPciInfo(virNodeDevicePtr dev,
                               unsigned *domain,
                               unsigned *bus,
                               unsigned *slot,
                               unsigned *function)
2062 2063 2064 2065 2066 2067 2068 2069 2070 2071
{
    virNodeDeviceDefPtr def = NULL;
    virNodeDevCapsDefPtr cap;
    char *xml = NULL;
    int ret = -1;

    xml = virNodeDeviceGetXMLDesc(dev, 0);
    if (!xml)
        goto out;

2072
    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089
    if (!def)
        goto out;

    cap = def->caps;
    while (cap) {
        if (cap->type == VIR_NODE_DEV_CAP_PCI_DEV) {
            *domain   = cap->data.pci_dev.domain;
            *bus      = cap->data.pci_dev.bus;
            *slot     = cap->data.pci_dev.slot;
            *function = cap->data.pci_dev.function;
            break;
        }

        cap = cap->next;
    }

    if (!cap) {
2090 2091
        virReportError(VIR_ERR_INVALID_ARG,
                       _("device %s is not a PCI device"), dev->name);
2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102
        goto out;
    }

    ret = 0;
out:
    virNodeDeviceDefFree(def);
    VIR_FREE(xml);
    return ret;
}

static int
2103
xenUnifiedNodeDeviceDettach(virNodeDevicePtr dev)
2104 2105 2106 2107 2108 2109 2110 2111
{
    pciDevice *pci;
    unsigned domain, bus, slot, function;
    int ret = -1;

    if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
        return -1;

2112
    pci = pciGetDevice(domain, bus, slot, function);
2113 2114 2115
    if (!pci)
        return -1;

2116
    if (pciDettachDevice(pci, NULL, NULL, "pciback") < 0)
2117 2118 2119 2120
        goto out;

    ret = 0;
out:
2121
    pciFreeDevice(pci);
2122 2123 2124
    return ret;
}

2125
static int
2126
xenUnifiedNodeDeviceAssignedDomainId(virNodeDevicePtr dev)
2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163
{
    int numdomains;
    int ret = -1, i;
    int *ids = NULL;
    char *bdf = NULL;
    char *xref = NULL;
    unsigned int domain, bus, slot, function;
    virConnectPtr conn = dev->conn;
    xenUnifiedPrivatePtr priv = conn->privateData;

    /* Get active domains */
    numdomains = xenUnifiedNumOfDomains(conn);
    if (numdomains < 0) {
        return ret;
    }
    if (numdomains > 0){
        if (VIR_ALLOC_N(ids, numdomains) < 0) {
            virReportOOMError();
            goto out;
        }
        if ((numdomains = xenUnifiedListDomains(conn, &ids[0], numdomains)) < 0) {
            goto out;
        }
    }

    /* Get pci bdf */
    if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
        goto out;

    if (virAsprintf(&bdf, "%04x:%02x:%02x.%0x",
                    domain, bus, slot, function) < 0) {
        virReportOOMError();
        goto out;
    }

    xenUnifiedLock(priv);
    /* Check if bdf is assigned to one of active domains */
2164
    for (i = 0; i < numdomains; i++) {
2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182
        xref = xenStoreDomainGetPCIID(conn, ids[i], bdf);
        if (xref == NULL) {
            continue;
        } else {
            ret = ids[i];
            break;
        }
    }
    xenUnifiedUnlock(priv);

    VIR_FREE(xref);
    VIR_FREE(bdf);
out:
    VIR_FREE(ids);

    return ret;
}

2183
static int
2184
xenUnifiedNodeDeviceReAttach(virNodeDevicePtr dev)
2185 2186 2187 2188
{
    pciDevice *pci;
    unsigned domain, bus, slot, function;
    int ret = -1;
2189
    int domid;
2190 2191 2192 2193

    if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
        return -1;

2194
    pci = pciGetDevice(domain, bus, slot, function);
2195 2196 2197
    if (!pci)
        return -1;

2198 2199
    /* Check if device is assigned to an active guest */
    if ((domid = xenUnifiedNodeDeviceAssignedDomainId(dev)) >= 0) {
2200 2201 2202
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Device %s has been assigned to guest %d"),
                       dev->name, domid);
2203 2204 2205
        goto out;
    }

2206
    if (pciReAttachDevice(pci, NULL, NULL, "pciback") < 0)
2207 2208 2209 2210
        goto out;

    ret = 0;
out:
2211
    pciFreeDevice(pci);
2212 2213 2214 2215
    return ret;
}

static int
2216
xenUnifiedNodeDeviceReset(virNodeDevicePtr dev)
2217 2218 2219 2220 2221 2222 2223 2224
{
    pciDevice *pci;
    unsigned domain, bus, slot, function;
    int ret = -1;

    if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
        return -1;

2225
    pci = pciGetDevice(domain, bus, slot, function);
2226 2227 2228
    if (!pci)
        return -1;

2229
    if (pciResetDevice(pci, NULL, NULL) < 0)
2230 2231 2232 2233
        goto out;

    ret = 0;
out:
2234
    pciFreeDevice(pci);
2235 2236 2237 2238
    return ret;
}


2239 2240
static int
xenUnifiedDomainOpenConsole(virDomainPtr dom,
2241
                            const char *dev_name,
2242 2243 2244 2245 2246 2247 2248 2249 2250 2251
                            virStreamPtr st,
                            unsigned int flags)
{
    virDomainDefPtr def = NULL;
    int ret = -1;
    virDomainChrDefPtr chr = NULL;

    virCheckFlags(0, -1);

    if (dom->id == -1) {
2252 2253
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
2254 2255 2256
        goto cleanup;
    }

2257
    if (dev_name) {
2258
        /* XXX support device aliases in future */
2259 2260
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Named device aliases are not supported"));
2261 2262 2263 2264 2265 2266 2267
        goto cleanup;
    }

    def = xenDaemonDomainFetch(dom->conn, dom->id, dom->name, NULL);
    if (!def)
        goto cleanup;

2268 2269
    if (def->nconsoles)
        chr = def->consoles[0];
2270 2271 2272 2273
    else if (def->nserials)
        chr = def->serials[0];

    if (!chr) {
2274 2275
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("cannot find default console device"));
2276 2277 2278
        goto cleanup;
    }

2279
    if (chr->source.type != VIR_DOMAIN_CHR_TYPE_PTY) {
2280 2281
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("character device %s is not using a PTY"), dev_name);
2282 2283 2284
        goto cleanup;
    }

2285
    if (virFDStreamOpenFile(st, chr->source.data.file.path,
E
Eric Blake 已提交
2286
                            0, 0, O_RDWR) < 0)
2287 2288 2289 2290 2291 2292 2293
        goto cleanup;

    ret = 0;
cleanup:
    virDomainDefFree(def);
    return ret;
}
E
Eric Blake 已提交
2294
/*----- Register with libvirt.c, and initialize Xen drivers. -----*/
2295 2296 2297

/* The interface which we export upwards to libvirt.c. */
static virDriver xenUnifiedDriver = {
2298 2299
    .no = VIR_DRV_XEN_UNIFIED,
    .name = "Xen",
2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317
    .open = xenUnifiedOpen, /* 0.0.3 */
    .close = xenUnifiedClose, /* 0.0.3 */
    .supports_feature = xenUnifiedSupportsFeature, /* 0.3.2 */
    .type = xenUnifiedType, /* 0.0.3 */
    .version = xenUnifiedGetVersion, /* 0.0.3 */
    .getHostname = virGetHostname, /* 0.7.3 */
    .getMaxVcpus = xenUnifiedGetMaxVcpus, /* 0.2.1 */
    .nodeGetInfo = xenUnifiedNodeGetInfo, /* 0.1.0 */
    .getCapabilities = xenUnifiedGetCapabilities, /* 0.2.1 */
    .listDomains = xenUnifiedListDomains, /* 0.0.3 */
    .numOfDomains = xenUnifiedNumOfDomains, /* 0.0.3 */
    .domainCreateXML = xenUnifiedDomainCreateXML, /* 0.0.3 */
    .domainLookupByID = xenUnifiedDomainLookupByID, /* 0.0.3 */
    .domainLookupByUUID = xenUnifiedDomainLookupByUUID, /* 0.0.5 */
    .domainLookupByName = xenUnifiedDomainLookupByName, /* 0.0.3 */
    .domainSuspend = xenUnifiedDomainSuspend, /* 0.0.3 */
    .domainResume = xenUnifiedDomainResume, /* 0.0.3 */
    .domainShutdown = xenUnifiedDomainShutdown, /* 0.0.3 */
2318
    .domainShutdownFlags = xenUnifiedDomainShutdownFlags, /* 0.9.10 */
2319 2320
    .domainReboot = xenUnifiedDomainReboot, /* 0.1.0 */
    .domainDestroy = xenUnifiedDomainDestroy, /* 0.0.3 */
2321
    .domainDestroyFlags = xenUnifiedDomainDestroyFlags, /* 0.9.4 */
2322 2323 2324 2325 2326 2327 2328
    .domainGetOSType = xenUnifiedDomainGetOSType, /* 0.0.3 */
    .domainGetMaxMemory = xenUnifiedDomainGetMaxMemory, /* 0.0.3 */
    .domainSetMaxMemory = xenUnifiedDomainSetMaxMemory, /* 0.0.3 */
    .domainSetMemory = xenUnifiedDomainSetMemory, /* 0.1.1 */
    .domainGetInfo = xenUnifiedDomainGetInfo, /* 0.0.3 */
    .domainGetState = xenUnifiedDomainGetState, /* 0.9.2 */
    .domainSave = xenUnifiedDomainSave, /* 0.0.3 */
2329
    .domainSaveFlags = xenUnifiedDomainSaveFlags, /* 0.9.4 */
2330 2331 2332
    .domainManagedSave = xenUnifiedDomainManagedSave, /* 1.0.1 */
    .domainHasManagedSaveImage = xenUnifiedDomainHasManagedSaveImage, /* 1.0.1 */
    .domainManagedSaveRemove = xenUnifiedDomainManagedSaveRemove, /* 1.0.1 */
2333
    .domainRestore = xenUnifiedDomainRestore, /* 0.0.3 */
2334
    .domainRestoreFlags = xenUnifiedDomainRestoreFlags, /* 0.9.4 */
2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350
    .domainCoreDump = xenUnifiedDomainCoreDump, /* 0.1.9 */
    .domainSetVcpus = xenUnifiedDomainSetVcpus, /* 0.1.4 */
    .domainSetVcpusFlags = xenUnifiedDomainSetVcpusFlags, /* 0.8.5 */
    .domainGetVcpusFlags = xenUnifiedDomainGetVcpusFlags, /* 0.8.5 */
    .domainPinVcpu = xenUnifiedDomainPinVcpu, /* 0.1.4 */
    .domainGetVcpus = xenUnifiedDomainGetVcpus, /* 0.1.4 */
    .domainGetMaxVcpus = xenUnifiedDomainGetMaxVcpus, /* 0.2.1 */
    .domainGetXMLDesc = xenUnifiedDomainGetXMLDesc, /* 0.0.3 */
    .domainXMLFromNative = xenUnifiedDomainXMLFromNative, /* 0.6.4 */
    .domainXMLToNative = xenUnifiedDomainXMLToNative, /* 0.6.4 */
    .listDefinedDomains = xenUnifiedListDefinedDomains, /* 0.1.1 */
    .numOfDefinedDomains = xenUnifiedNumOfDefinedDomains, /* 0.1.5 */
    .domainCreate = xenUnifiedDomainCreate, /* 0.1.1 */
    .domainCreateWithFlags = xenUnifiedDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = xenUnifiedDomainDefineXML, /* 0.1.1 */
    .domainUndefine = xenUnifiedDomainUndefine, /* 0.1.1 */
2351
    .domainUndefineFlags = xenUnifiedDomainUndefineFlags, /* 0.9.4 */
2352 2353 2354 2355 2356 2357 2358 2359 2360
    .domainAttachDevice = xenUnifiedDomainAttachDevice, /* 0.1.9 */
    .domainAttachDeviceFlags = xenUnifiedDomainAttachDeviceFlags, /* 0.7.7 */
    .domainDetachDevice = xenUnifiedDomainDetachDevice, /* 0.1.9 */
    .domainDetachDeviceFlags = xenUnifiedDomainDetachDeviceFlags, /* 0.7.7 */
    .domainUpdateDeviceFlags = xenUnifiedDomainUpdateDeviceFlags, /* 0.8.0 */
    .domainGetAutostart = xenUnifiedDomainGetAutostart, /* 0.4.4 */
    .domainSetAutostart = xenUnifiedDomainSetAutostart, /* 0.4.4 */
    .domainGetSchedulerType = xenUnifiedDomainGetSchedulerType, /* 0.2.3 */
    .domainGetSchedulerParameters = xenUnifiedDomainGetSchedulerParameters, /* 0.2.3 */
2361
    .domainGetSchedulerParametersFlags = xenUnifiedDomainGetSchedulerParametersFlags, /* 0.9.2 */
2362
    .domainSetSchedulerParameters = xenUnifiedDomainSetSchedulerParameters, /* 0.2.3 */
2363
    .domainSetSchedulerParametersFlags = xenUnifiedDomainSetSchedulerParametersFlags, /* 0.9.2 */
2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384
    .domainMigratePrepare = xenUnifiedDomainMigratePrepare, /* 0.3.2 */
    .domainMigratePerform = xenUnifiedDomainMigratePerform, /* 0.3.2 */
    .domainMigrateFinish = xenUnifiedDomainMigrateFinish, /* 0.3.2 */
    .domainBlockStats = xenUnifiedDomainBlockStats, /* 0.3.2 */
    .domainInterfaceStats = xenUnifiedDomainInterfaceStats, /* 0.3.2 */
    .domainBlockPeek = xenUnifiedDomainBlockPeek, /* 0.4.4 */
    .nodeGetCellsFreeMemory = xenUnifiedNodeGetCellsFreeMemory, /* 0.3.3 */
    .nodeGetFreeMemory = xenUnifiedNodeGetFreeMemory, /* 0.3.3 */
    .domainEventRegister = xenUnifiedDomainEventRegister, /* 0.5.0 */
    .domainEventDeregister = xenUnifiedDomainEventDeregister, /* 0.5.0 */
    .nodeDeviceDettach = xenUnifiedNodeDeviceDettach, /* 0.6.1 */
    .nodeDeviceReAttach = xenUnifiedNodeDeviceReAttach, /* 0.6.1 */
    .nodeDeviceReset = xenUnifiedNodeDeviceReset, /* 0.6.1 */
    .isEncrypted = xenUnifiedIsEncrypted, /* 0.7.3 */
    .isSecure = xenUnifiedIsSecure, /* 0.7.3 */
    .domainIsActive = xenUnifiedDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = xenUnifiedDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = xenUnifiedDomainIsUpdated, /* 0.8.6 */
    .domainEventRegisterAny = xenUnifiedDomainEventRegisterAny, /* 0.8.0 */
    .domainEventDeregisterAny = xenUnifiedDomainEventDeregisterAny, /* 0.8.0 */
    .domainOpenConsole = xenUnifiedDomainOpenConsole, /* 0.8.6 */
2385
    .isAlive = xenUnifiedIsAlive, /* 0.9.8 */
2386
    .nodeSuspendForDuration = nodeSuspendForDuration, /* 0.9.8 */
2387 2388
    .nodeGetMemoryParameters = nodeGetMemoryParameters, /* 0.10.2 */
    .nodeSetMemoryParameters = nodeSetMemoryParameters, /* 0.10.2 */
2389 2390
};

2391
/**
2392
 * xenRegister:
2393 2394 2395 2396 2397
 *
 * Register xen related drivers
 *
 * Returns the driver priority or -1 in case of error.
 */
2398
int
2399
xenRegister(void)
2400
{
J
John Levon 已提交
2401
#ifdef WITH_LIBVIRTD
2402
    if (virRegisterStateDriver(&state_driver) == -1) return -1;
J
John Levon 已提交
2403 2404
#endif

2405
    return virRegisterDriver(&xenUnifiedDriver);
2406 2407
}

2408 2409 2410 2411 2412 2413 2414 2415 2416
/**
 * xenUnifiedDomainInfoListFree:
 *
 * Free the Domain Info List
 */
void
xenUnifiedDomainInfoListFree(xenUnifiedDomainInfoListPtr list)
{
    int i;
J
John Levon 已提交
2417 2418 2419 2420

    if (list == NULL)
        return;

2421 2422 2423 2424
    for (i=0; i<list->count; i++) {
        VIR_FREE(list->doms[i]->name);
        VIR_FREE(list->doms[i]);
    }
2425
    VIR_FREE(list->doms);
2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447
    VIR_FREE(list);
}

/**
 * xenUnifiedAddDomainInfo:
 *
 * Add name and uuid to the domain info list
 *
 * Returns: 0 on success, -1 on failure
 */
int
xenUnifiedAddDomainInfo(xenUnifiedDomainInfoListPtr list,
                        int id, char *name,
                        unsigned char *uuid)
{
    xenUnifiedDomainInfoPtr info;
    int n;

    /* check if we already have this callback on our list */
    for (n=0; n < list->count; n++) {
        if (STREQ(list->doms[n]->name, name) &&
            !memcmp(list->doms[n]->uuid, uuid, VIR_UUID_BUFLEN)) {
2448
            VIR_DEBUG("WARNING: dom already tracked");
2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470
            return -1;
        }
    }

    if (VIR_ALLOC(info) < 0)
        goto memory_error;
    if (!(info->name = strdup(name)))
        goto memory_error;

    memcpy(info->uuid, uuid, VIR_UUID_BUFLEN);
    info->id = id;

    /* Make space on list */
    n = list->count;
    if (VIR_REALLOC_N(list->doms, n + 1) < 0) {
        goto memory_error;
    }

    list->doms[n] = info;
    list->count++;
    return 0;
memory_error:
2471
    virReportOOMError();
2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491
    if (info)
        VIR_FREE(info->name);
    VIR_FREE(info);
    return -1;
}

/**
 * xenUnifiedRemoveDomainInfo:
 *
 * Removes name and uuid to the domain info list
 *
 * Returns: 0 on success, -1 on failure
 */
int
xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr list,
                           int id, char *name,
                           unsigned char *uuid)
{
    int i;
    for (i = 0 ; i < list->count ; i++) {
2492
        if (list->doms[i]->id == id &&
2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516
            STREQ(list->doms[i]->name, name) &&
            !memcmp(list->doms[i]->uuid, uuid, VIR_UUID_BUFLEN)) {

            VIR_FREE(list->doms[i]->name);
            VIR_FREE(list->doms[i]);

            if (i < (list->count - 1))
                memmove(list->doms + i,
                        list->doms + i + 1,
                        sizeof(*(list->doms)) *
                                (list->count - (i + 1)));

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

            return 0;
        }
    }
    return -1;
}

2517

2518 2519
/**
 * xenUnifiedDomainEventDispatch:
D
Daniel P. Berrange 已提交
2520 2521
 * @priv: the connection to dispatch events on
 * @event: the event to dispatch
2522 2523 2524
 *
 * Dispatch domain events to registered callbacks
 *
D
Daniel P. Berrange 已提交
2525 2526
 * The caller must hold the lock in 'priv' before invoking
 *
2527
 */
2528
void xenUnifiedDomainEventDispatch(xenUnifiedPrivatePtr priv,
2529
                                    virDomainEventPtr event)
2530
{
D
Daniel P. Berrange 已提交
2531
    if (!priv)
2532
        return;
2533

2534
    virDomainEventStateQueue(priv->domainEvents, event);
D
Daniel P. Berrange 已提交
2535 2536 2537 2538 2539 2540 2541 2542 2543 2544
}

void xenUnifiedLock(xenUnifiedPrivatePtr priv)
{
    virMutexLock(&priv->lock);
}

void xenUnifiedUnlock(xenUnifiedPrivatePtr priv)
{
    virMutexUnlock(&priv->lock);
2545
}