xen_driver.c 68.6 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 (!(priv->xmlopt = virDomainXMLOptionNew(NULL, NULL, NULL)))
405 406
        goto fail;

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

417 418 419 420 421 422 423 424 425 426 427
    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;
    }

428
    return VIR_DRV_OPEN_SUCCESS;
429

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

444 445 446
#define GET_PRIVATE(conn) \
    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) (conn)->privateData

447
static int
448
xenUnifiedClose(virConnectPtr conn)
449
{
450
    GET_PRIVATE(conn);
451
    int i;
452

453
    virObjectUnref(priv->caps);
454
    virObjectUnref(priv->xmlopt);
455
    virDomainEventStateFree(priv->domainEvents);
456

457
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
458 459
        if (priv->opened[i])
            drivers[i]->xenClose(conn);
460

461
    VIR_FREE(priv->saveDir);
D
Daniel P. Berrange 已提交
462 463
    virMutexDestroy(&priv->lock);
    VIR_FREE(conn->privateData);
464

465
    return 0;
466 467
}

468 469 470 471 472 473 474 475 476 477 478

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


479
static const char *
480
xenUnifiedType(virConnectPtr conn)
481
{
482
    GET_PRIVATE(conn);
483
    int i;
484

485
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
486 487
        if (priv->opened[i])
            return "Xen";
488

489
    return NULL;
490 491
}

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

505
static int
506
xenUnifiedGetVersion(virConnectPtr conn, unsigned long *hvVer)
507
{
508
    GET_PRIVATE(conn);
509
    int i;
510

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

517
    return -1;
518 519
}

520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539
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;
}

540 541 542 543 544 545 546
static int
xenUnifiedIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    /* XenD reconnects for each request */
    return 1;
}

547
int
548
xenUnifiedGetMaxVcpus(virConnectPtr conn, const char *type)
549
{
550
    GET_PRIVATE(conn);
551

552
    if (type && STRCASENEQ(type, "Xen")) {
553
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
554 555
        return -1;
    }
556

557
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
558
        return xenHypervisorGetMaxVcpus(conn, type);
559
    else {
560
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
561 562
        return -1;
    }
563 564 565
}

static int
566
xenUnifiedNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
567
{
568
    GET_PRIVATE(conn);
569

570 571
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonNodeGetInfo(conn, info);
572
    return -1;
573 574 575
}

static char *
576
xenUnifiedGetCapabilities(virConnectPtr conn)
577
{
D
Daniel P. Berrange 已提交
578 579
    xenUnifiedPrivatePtr priv = conn->privateData;
    char *xml;
580

D
Daniel P. Berrange 已提交
581
    if (!(xml = virCapabilitiesFormatXML(priv->caps))) {
582
        virReportOOMError();
D
Daniel P. Berrange 已提交
583 584
        return NULL;
    }
585

D
Daniel P. Berrange 已提交
586
    return xml;
587 588 589
}

static int
590
xenUnifiedListDomains(virConnectPtr conn, int *ids, int maxids)
591
{
592
    GET_PRIVATE(conn);
593
    int ret;
594

595 596
    /* Try xenstore. */
    if (priv->opened[XEN_UNIFIED_XS_OFFSET]) {
597
        ret = xenStoreListDomains(conn, ids, maxids);
598 599
        if (ret >= 0) return ret;
    }
600

601 602
    /* Try HV. */
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
603
        ret = xenHypervisorListDomains(conn, ids, maxids);
604 605 606 607 608
        if (ret >= 0) return ret;
    }

    /* Try xend. */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
609
        ret = xenDaemonListDomains(conn, ids, maxids);
610 611 612
        if (ret >= 0) return ret;
    }

613
    return -1;
614 615 616
}

static int
617
xenUnifiedNumOfDomains(virConnectPtr conn)
618
{
619
    GET_PRIVATE(conn);
620
    int ret;
621

622 623
    /* Try xenstore. */
    if (priv->opened[XEN_UNIFIED_XS_OFFSET]) {
624
        ret = xenStoreNumOfDomains(conn);
625 626 627 628 629
        if (ret >= 0) return ret;
    }

    /* Try HV. */
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
630
        ret = xenHypervisorNumOfDomains(conn);
631 632 633 634 635
        if (ret >= 0) return ret;
    }

    /* Try xend. */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
636
        ret = xenDaemonNumOfDomains(conn);
637 638 639
        if (ret >= 0) return ret;
    }

640
    return -1;
641 642 643
}

static virDomainPtr
644 645
xenUnifiedDomainCreateXML(virConnectPtr conn,
                          const char *xmlDesc, unsigned int flags)
646
{
647
    GET_PRIVATE(conn);
648

649 650
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonCreateXML(conn, xmlDesc, flags);
651
    return NULL;
652 653
}

654 655 656 657
/* 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.
 */
658
static virDomainPtr
659
xenUnifiedDomainLookupByID(virConnectPtr conn, int id)
660
{
661
    GET_PRIVATE(conn);
662
    virDomainPtr ret;
663

664 665 666
    /* Reset any connection-level errors in virterror first, in case
     * there is one hanging around from a previous call.
     */
667
    virConnResetLastError(conn);
668

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

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

683
    /* Not found. */
684
    virReportError(VIR_ERR_NO_DOMAIN, __FUNCTION__);
685
    return NULL;
686 687 688
}

static virDomainPtr
689 690
xenUnifiedDomainLookupByUUID(virConnectPtr conn,
                             const unsigned char *uuid)
691
{
692
    GET_PRIVATE(conn);
693
    virDomainPtr ret;
694

695 696 697
    /* Reset any connection-level errors in virterror first, in case
     * there is one hanging around from a previous call.
     */
698
    virConnResetLastError(conn);
699

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

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

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

    /* Not found. */
722
    virReportError(VIR_ERR_NO_DOMAIN, __FUNCTION__);
723
    return NULL;
724 725 726
}

static virDomainPtr
727 728
xenUnifiedDomainLookupByName(virConnectPtr conn,
                             const char *name)
729
{
730
    GET_PRIVATE(conn);
731
    virDomainPtr ret;
732

733 734 735
    /* Reset any connection-level errors in virterror first, in case
     * there is one hanging around from a previous call.
     */
736
    virConnResetLastError(conn);
737 738 739

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

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

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

759
    /* Not found. */
760
    virReportError(VIR_ERR_NO_DOMAIN, __FUNCTION__);
761
    return NULL;
762 763
}

764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782

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
783
xenUnifiedDomainIsPersistent(virDomainPtr dom)
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 810 811 812 813
{
    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) {
814
                        virReportOOMError();
815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832
                        goto done;
                    }
                    if (access(path, R_OK) == 0)
                        ret = 1;
                    else if (errno == ENOENT)
                        ret = 0;
                }
            }
        }
    }

done:
    if (currdom)
        virDomainFree(currdom);

    return ret;
}

833 834 835 836 837 838
static int
xenUnifiedDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
{
    return 0;
}

839
static int
840
xenUnifiedDomainSuspend(virDomainPtr dom)
841
{
842
    GET_PRIVATE(dom->conn);
843
    int i;
844

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

855
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
E
Eric Blake 已提交
856
        xenHypervisorPauseDomain(dom) == 0)
857
        return 0;
858

859
    return -1;
860 861 862
}

static int
863
xenUnifiedDomainResume(virDomainPtr dom)
864
{
865
    GET_PRIVATE(dom->conn);
866
    int i;
867

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

878
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
E
Eric Blake 已提交
879
        xenHypervisorResumeDomain(dom) == 0)
880
        return 0;
881

882
    return -1;
883 884 885
}

static int
886 887
xenUnifiedDomainShutdownFlags(virDomainPtr dom,
                              unsigned int flags)
888
{
889
    GET_PRIVATE(dom->conn);
890
    int i;
891

892 893
    virCheckFlags(0, -1);

894 895
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
E
Eric Blake 已提交
896
            drivers[i]->xenDomainShutdown &&
897
            drivers[i]->xenDomainShutdown(dom) == 0)
898
            return 0;
899

900
    return -1;
901 902
}

903 904 905 906 907 908
static int
xenUnifiedDomainShutdown(virDomainPtr dom)
{
    return xenUnifiedDomainShutdownFlags(dom, 0);
}

909
static int
910
xenUnifiedDomainReboot(virDomainPtr dom, unsigned int flags)
911
{
912
    GET_PRIVATE(dom->conn);
913
    int i;
914

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

921
    return -1;
922 923
}

924 925 926 927 928 929 930 931 932 933 934 935 936 937 938
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 已提交
939 940
            drivers[i]->xenDomainDestroyFlags &&
            drivers[i]->xenDomainDestroyFlags(dom, flags) == 0)
941 942 943
            return 0;

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
E
Eric Blake 已提交
944
        xenHypervisorDestroyDomainFlags(dom, flags) == 0)
945 946 947 948 949
        return 0;

    return -1;
}

950 951 952 953 954 955
static int
xenUnifiedDomainDestroy(virDomainPtr dom)
{
    return xenUnifiedDomainDestroyFlags(dom, 0);
}

956
static char *
957
xenUnifiedDomainGetOSType(virDomainPtr dom)
958
{
959
    GET_PRIVATE(dom->conn);
960 961
    int i;
    char *ret;
962

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

969
    return NULL;
970 971
}

972
static unsigned long long
973
xenUnifiedDomainGetMaxMemory(virDomainPtr dom)
974
{
975
    GET_PRIVATE(dom->conn);
976
    int i;
977
    unsigned long long ret;
978

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

985
    return 0;
986 987 988
}

static int
989
xenUnifiedDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
990
{
991
    GET_PRIVATE(dom->conn);
992
    int i;
993

994 995
    /* Prefer xend for setting max memory */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
996
        if (xenDaemonDomainSetMaxMemory(dom, memory) == 0)
997 998 999
            return 0;
    }

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

1007
    return -1;
1008 1009 1010
}

static int
1011
xenUnifiedDomainSetMemory(virDomainPtr dom, unsigned long memory)
1012
{
1013
    GET_PRIVATE(dom->conn);
1014
    int i;
1015

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

1022
    return -1;
1023 1024 1025
}

static int
1026
xenUnifiedDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
1027
{
1028
    GET_PRIVATE(dom->conn);
1029
    int i;
1030

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

1037
    return -1;
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 1077 1078 1079 1080
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;
}

1081
static int
1082 1083
xenUnifiedDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml,
                          unsigned int flags)
1084
{
1085
    GET_PRIVATE(dom->conn);
1086

1087 1088
    virCheckFlags(0, -1);
    if (dxml) {
1089 1090
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1091 1092 1093
        return -1;
    }

1094 1095
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonDomainSave(dom, to);
1096
    return -1;
1097 1098 1099
}

static int
1100 1101 1102 1103 1104
xenUnifiedDomainSave(virDomainPtr dom, const char *to)
{
    return xenUnifiedDomainSaveFlags(dom, to, NULL, 0);
}

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 1172 1173 1174 1175
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;
}

1176 1177 1178
static int
xenUnifiedDomainRestoreFlags(virConnectPtr conn, const char *from,
                             const char *dxml, unsigned int flags)
1179
{
1180
    GET_PRIVATE(conn);
1181

1182 1183
    virCheckFlags(0, -1);
    if (dxml) {
1184 1185
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1186 1187 1188
        return -1;
    }

1189 1190
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonDomainRestore(conn, from);
1191
    return -1;
1192 1193
}

1194
static int
1195
xenUnifiedDomainRestore(virConnectPtr conn, const char *from)
1196 1197 1198 1199
{
    return xenUnifiedDomainRestoreFlags(conn, from, NULL, 0);
}

1200
static int
1201
xenUnifiedDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
1202
{
1203
    GET_PRIVATE(dom->conn);
1204

1205 1206
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonDomainCoreDump(dom, to, flags);
1207
    return -1;
1208 1209 1210
}

static int
1211 1212
xenUnifiedDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
                              unsigned int flags)
1213
{
1214
    GET_PRIVATE(dom->conn);
1215
    int ret;
1216

1217 1218 1219 1220 1221 1222 1223 1224 1225
    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)) {
1226 1227
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
1228 1229 1230
        return -1;
    }
    if (!nvcpus || (unsigned short) nvcpus != nvcpus) {
1231 1232
        virReportError(VIR_ERR_INVALID_ARG,
                       _("argument out of range: %d"), nvcpus);
1233 1234 1235
        return -1;
    }

1236 1237 1238
    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250
    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);
1251

1252
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1253
    return -1;
1254 1255
}

1256
static int
1257
xenUnifiedDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
1258
{
1259 1260 1261 1262 1263 1264
    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) {
1265
        GET_PRIVATE(dom->conn);
1266
        if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
1267
            flags |= VIR_DOMAIN_VCPU_CONFIG;
1268
        return xenUnifiedDomainSetVcpusFlags(dom, nvcpus, flags);
1269
    }
1270
    return -1;
1271 1272
}

1273
static int
1274 1275
xenUnifiedDomainPinVcpu(virDomainPtr dom, unsigned int vcpu,
                        unsigned char *cpumap, int maplen)
1276
{
1277
    GET_PRIVATE(dom->conn);
1278
    int i;
1279

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

1286
    return -1;
1287 1288 1289
}

static int
1290 1291 1292
xenUnifiedDomainGetVcpus(virDomainPtr dom,
                         virVcpuInfoPtr info, int maxinfo,
                         unsigned char *cpumaps, int maplen)
1293
{
1294
    GET_PRIVATE(dom->conn);
1295
    int i, ret;
1296

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

static int
1307
xenUnifiedDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
1308
{
1309
    GET_PRIVATE(dom->conn);
1310
    int ret;
1311

1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327
    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);
1328

1329
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1330
    return -1;
1331 1332
}

1333
static int
1334
xenUnifiedDomainGetMaxVcpus(virDomainPtr dom)
1335 1336 1337 1338 1339
{
    return xenUnifiedDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
                                               VIR_DOMAIN_VCPU_MAXIMUM));
}

1340
static char *
1341
xenUnifiedDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
1342
{
1343
    GET_PRIVATE(dom->conn);
1344

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

1360
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1361
    return NULL;
1362 1363
}

1364 1365 1366 1367 1368

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

E
Eric Blake 已提交
1379 1380
    virCheckFlags(0, NULL);

1381 1382
    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
1383 1384
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), format);
1385 1386 1387 1388
        return NULL;
    }

    if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
1389
        conf = virConfReadMem(config, strlen(config), 0);
1390 1391 1392
        if (!conf)
            goto cleanup;

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

1406
    ret = virDomainDefFormat(def, 0);
1407 1408 1409

cleanup:
    virDomainDefFree(def);
1410 1411
    if (conf)
        virConfFree(conf);
1412 1413 1414 1415 1416 1417 1418 1419 1420
    return ret;
}


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

E
Eric Blake 已提交
1428 1429
    virCheckFlags(0, NULL);

1430 1431
    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
1432 1433
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), format);
1434 1435 1436
        goto cleanup;
    }

1437
    if (!(def = virDomainDefParseString(priv->caps, priv->xmlopt,
1438
                                        xmlData, 1 << VIR_DOMAIN_VIRT_XEN, 0)))
1439 1440 1441 1442
        goto cleanup;

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

        if (VIR_ALLOC_N(ret, len) < 0) {
1448
            virReportOOMError();
1449 1450 1451 1452 1453 1454 1455 1456
            goto cleanup;
        }

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

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


1468
static int
1469 1470 1471 1472 1473 1474 1475 1476
xenUnifiedDomainMigratePrepare(virConnectPtr dconn,
                               char **cookie,
                               int *cookielen,
                               const char *uri_in,
                               char **uri_out,
                               unsigned long flags,
                               const char *dname,
                               unsigned long resource)
1477 1478 1479
{
    GET_PRIVATE(dconn);

E
Eric Blake 已提交
1480 1481
    virCheckFlags(XEN_MIGRATION_FLAGS, -1);

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

1487
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1488 1489 1490 1491
    return -1;
}

static int
1492 1493 1494 1495 1496 1497 1498
xenUnifiedDomainMigratePerform(virDomainPtr dom,
                               const char *cookie,
                               int cookielen,
                               const char *uri,
                               unsigned long flags,
                               const char *dname,
                               unsigned long resource)
1499 1500 1501
{
    GET_PRIVATE(dom->conn);

E
Eric Blake 已提交
1502 1503
    virCheckFlags(XEN_MIGRATION_FLAGS, -1);

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

1508
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1509 1510 1511 1512
    return -1;
}

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

E
Eric Blake 已提交
1524 1525
    virCheckFlags(XEN_MIGRATION_FLAGS, NULL);

1526
    dom = xenUnifiedDomainLookupByName(dconn, dname);
1527 1528 1529 1530 1531
    if (! dom) {
        return NULL;
    }

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

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

        /* Free additional reference added by Define */
1547
        virDomainFree(dom_new);
1548 1549
    }

1550
    VIR_FREE(domain_xml);
1551 1552 1553 1554 1555

    return dom;


failure:
1556
    virDomainFree(dom);
1557

1558
    VIR_FREE(domain_xml);
1559 1560

    return NULL;
1561 1562
}

1563
static int
1564 1565
xenUnifiedListDefinedDomains(virConnectPtr conn, char **const names,
                             int maxnames)
1566
{
1567
    GET_PRIVATE(conn);
1568 1569
    int i;
    int ret;
1570

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

1577
    return -1;
1578 1579 1580
}

static int
1581
xenUnifiedNumOfDefinedDomains(virConnectPtr conn)
1582
{
1583
    GET_PRIVATE(conn);
1584 1585
    int i;
    int ret;
1586

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

1593
    return -1;
1594 1595 1596
}

static int
1597
xenUnifiedDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
1598
{
1599
    GET_PRIVATE(dom->conn);
1600
    int i;
1601 1602
    int ret = -1;
    char *name = NULL;
1603

1604 1605
    virCheckFlags(0, -1);

1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619
    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 已提交
1620
        if (priv->opened[i] && drivers[i]->xenDomainCreate &&
1621 1622 1623 1624 1625
            drivers[i]->xenDomainCreate(dom) == 0) {
            ret = 0;
            goto cleanup;
        }
    }
1626

1627 1628 1629
cleanup:
    VIR_FREE(name);
    return ret;
1630 1631
}

1632
static int
1633
xenUnifiedDomainCreate(virDomainPtr dom)
1634 1635 1636 1637
{
    return xenUnifiedDomainCreateWithFlags(dom, 0);
}

1638
static virDomainPtr
1639
xenUnifiedDomainDefineXML(virConnectPtr conn, const char *xml)
1640
{
1641
    GET_PRIVATE(conn);
1642 1643
    int i;
    virDomainPtr ret;
1644

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

1651
    return NULL;
1652 1653 1654
}

static int
1655
xenUnifiedDomainUndefineFlags(virDomainPtr dom, unsigned int flags)
1656
{
1657
    GET_PRIVATE(dom->conn);
1658
    int i;
1659

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

1666
    return -1;
1667 1668
}

1669
static int
1670
xenUnifiedDomainUndefine(virDomainPtr dom) {
1671 1672 1673
    return xenUnifiedDomainUndefineFlags(dom, 0);
}

1674
static int
1675
xenUnifiedDomainAttachDevice(virDomainPtr dom, const char *xml)
1676 1677 1678
{
    GET_PRIVATE(dom->conn);
    int i;
1679
    unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
1680

1681 1682 1683 1684 1685 1686
    /*
     * 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] &&
1687
        priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
1688
        flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
1689 1690

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

    return -1;
}

static int
1699 1700
xenUnifiedDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
1701
{
1702
    GET_PRIVATE(dom->conn);
1703
    int i;
1704

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

1710
    return -1;
1711 1712 1713
}

static int
1714
xenUnifiedDomainDetachDevice(virDomainPtr dom, const char *xml)
1715 1716 1717
{
    GET_PRIVATE(dom->conn);
    int i;
1718
    unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
1719

1720 1721 1722 1723 1724 1725
    /*
     * 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] &&
1726
        priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
1727
        flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
1728 1729

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

    return -1;
}

static int
1738 1739
xenUnifiedDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
1740
{
1741
    GET_PRIVATE(dom->conn);
1742
    int i;
1743

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

1749
    return -1;
1750 1751
}

1752
static int
1753 1754
xenUnifiedDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
1755 1756 1757
{
    GET_PRIVATE(dom->conn);

1758 1759
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonUpdateDeviceFlags(dom, xml, flags);
1760 1761 1762
    return -1;
}

1763
static int
1764
xenUnifiedDomainGetAutostart(virDomainPtr dom, int *autostart)
1765 1766 1767
{
    GET_PRIVATE(dom->conn);

1768
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
1769 1770 1771 1772 1773 1774
        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
            return xenXMDomainGetAutostart(dom, autostart);
    } else {
        if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
            return xenDaemonDomainGetAutostart(dom, autostart);
    }
1775

1776
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1777 1778 1779 1780
    return -1;
}

static int
1781
xenUnifiedDomainSetAutostart(virDomainPtr dom, int autostart)
1782 1783 1784
{
    GET_PRIVATE(dom->conn);

1785
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
1786 1787 1788 1789 1790 1791
        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
            return xenXMDomainSetAutostart(dom, autostart);
    } else {
        if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
            return xenDaemonDomainSetAutostart(dom, autostart);
    }
1792

1793
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1794 1795 1796
    return -1;
}

1797
static char *
1798
xenUnifiedDomainGetSchedulerType(virDomainPtr dom, int *nparams)
1799 1800 1801 1802 1803 1804
{
    GET_PRIVATE(dom->conn);
    int i;
    char *schedulertype;

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

static int
1815 1816 1817 1818
xenUnifiedDomainGetSchedulerParametersFlags(virDomainPtr dom,
                                            virTypedParameterPtr params,
                                            int *nparams,
                                            unsigned int flags)
1819 1820 1821 1822
{
    GET_PRIVATE(dom->conn);
    int i, ret;

1823 1824
    virCheckFlags(0, -1);

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

static int
1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848
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)
1849 1850 1851 1852
{
    GET_PRIVATE(dom->conn);
    int i, ret;

1853 1854
    virCheckFlags(0, -1);

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

1864
    return -1;
1865 1866
}

1867 1868 1869 1870 1871 1872 1873 1874 1875
static int
xenUnifiedDomainSetSchedulerParameters(virDomainPtr dom,
                                       virTypedParameterPtr params,
                                       int nparams)
{
    return xenUnifiedDomainSetSchedulerParametersFlags(dom, params,
                                                       nparams, 0);
}

1876
static int
1877 1878
xenUnifiedDomainBlockStats(virDomainPtr dom, const char *path,
                           struct _virDomainBlockStats *stats)
1879
{
1880
    GET_PRIVATE(dom->conn);
1881 1882

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

1885
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1886 1887 1888 1889
    return -1;
}

static int
1890 1891
xenUnifiedDomainInterfaceStats(virDomainPtr dom, const char *path,
                               struct _virDomainInterfaceStats *stats)
1892
{
1893
    GET_PRIVATE(dom->conn);
1894 1895

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

1898
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1899 1900 1901
    return -1;
}

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

E
Eric Blake 已提交
1910 1911
    virCheckFlags(0, -1);

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

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

1923
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
R
Richard W.M. Jones 已提交
1924 1925 1926
    return -1;
}

1927
static int
1928 1929
xenUnifiedNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems,
                                 int startCell, int maxCells)
1930
{
1931
    GET_PRIVATE(conn);
1932 1933

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

1937
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1938 1939 1940
    return -1;
}

1941
static unsigned long long
1942
xenUnifiedNodeGetFreeMemory(virConnectPtr conn)
1943 1944 1945
{
    unsigned long long freeMem = 0;
    int ret;
1946
    GET_PRIVATE(conn);
1947 1948

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
1949 1950
        ret = xenHypervisorNodeGetCellsFreeMemory(conn, &freeMem,
                                                  -1, 1);
1951
        if (ret != 1)
1952 1953
            return 0;
        return freeMem;
1954 1955
    }

1956
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1957
    return 0;
1958 1959
}

1960

1961
static int
1962 1963 1964 1965
xenUnifiedDomainEventRegister(virConnectPtr conn,
                              virConnectDomainEventCallback callback,
                              void *opaque,
                              virFreeCallback freefunc)
1966
{
1967
    GET_PRIVATE(conn);
D
Daniel P. Berrange 已提交
1968

1969
    int ret;
D
Daniel P. Berrange 已提交
1970
    xenUnifiedLock(priv);
1971

1972
    if (priv->xsWatch == -1) {
1973
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
D
Daniel P. Berrange 已提交
1974
        xenUnifiedUnlock(priv);
1975 1976 1977
        return -1;
    }

1978 1979
    ret = virDomainEventStateRegister(conn, priv->domainEvents,
                                      callback, opaque, freefunc);
1980

D
Daniel P. Berrange 已提交
1981
    xenUnifiedUnlock(priv);
1982
    return ret;
1983 1984
}

1985

1986
static int
1987 1988
xenUnifiedDomainEventDeregister(virConnectPtr conn,
                                virConnectDomainEventCallback callback)
1989 1990
{
    int ret;
1991
    GET_PRIVATE(conn);
D
Daniel P. Berrange 已提交
1992 1993
    xenUnifiedLock(priv);

1994
    if (priv->xsWatch == -1) {
1995
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
D
Daniel P. Berrange 已提交
1996
        xenUnifiedUnlock(priv);
1997 1998 1999
        return -1;
    }

2000 2001 2002
    ret = virDomainEventStateDeregister(conn,
                                        priv->domainEvents,
                                        callback);
2003

D
Daniel P. Berrange 已提交
2004
    xenUnifiedUnlock(priv);
2005 2006 2007
    return ret;
}

2008

2009 2010 2011 2012 2013 2014 2015 2016
static int
xenUnifiedDomainEventRegisterAny(virConnectPtr conn,
                                 virDomainPtr dom,
                                 int eventID,
                                 virConnectDomainEventGenericCallback callback,
                                 void *opaque,
                                 virFreeCallback freefunc)
{
2017
    GET_PRIVATE(conn);
2018 2019 2020 2021 2022

    int ret;
    xenUnifiedLock(priv);

    if (priv->xsWatch == -1) {
2023
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
2024 2025 2026 2027
        xenUnifiedUnlock(priv);
        return -1;
    }

2028 2029 2030
    if (virDomainEventStateRegisterID(conn, priv->domainEvents,
                                      dom, eventID,
                                      callback, opaque, freefunc, &ret) < 0)
2031
        ret = -1;
2032 2033

    xenUnifiedUnlock(priv);
2034
    return ret;
2035 2036 2037 2038 2039 2040 2041
}

static int
xenUnifiedDomainEventDeregisterAny(virConnectPtr conn,
                                   int callbackID)
{
    int ret;
2042
    GET_PRIVATE(conn);
2043 2044 2045
    xenUnifiedLock(priv);

    if (priv->xsWatch == -1) {
2046
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
2047 2048 2049 2050
        xenUnifiedUnlock(priv);
        return -1;
    }

2051 2052 2053
    ret = virDomainEventStateDeregisterID(conn,
                                          priv->domainEvents,
                                          callbackID);
2054 2055 2056 2057 2058 2059

    xenUnifiedUnlock(priv);
    return ret;
}


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

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

2076
    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093
    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) {
2094 2095
        virReportError(VIR_ERR_INVALID_ARG,
                       _("device %s is not a PCI device"), dev->name);
2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106
        goto out;
    }

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

static int
2107
xenUnifiedNodeDeviceDettach(virNodeDevicePtr dev)
2108
{
2109
    virPCIDevicePtr pci;
2110 2111 2112 2113 2114 2115
    unsigned domain, bus, slot, function;
    int ret = -1;

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

2116
    pci = virPCIDeviceNew(domain, bus, slot, function);
2117 2118 2119
    if (!pci)
        return -1;

2120
    if (virPCIDeviceDetach(pci, NULL, NULL, "pciback") < 0)
2121 2122 2123 2124
        goto out;

    ret = 0;
out:
2125
    virPCIDeviceFree(pci);
2126 2127 2128
    return ret;
}

2129
static int
2130
xenUnifiedNodeDeviceAssignedDomainId(virNodeDevicePtr dev)
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 2164 2165 2166 2167
{
    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 */
2168
    for (i = 0; i < numdomains; i++) {
2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186
        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;
}

2187
static int
2188
xenUnifiedNodeDeviceReAttach(virNodeDevicePtr dev)
2189
{
2190
    virPCIDevicePtr pci;
2191 2192
    unsigned domain, bus, slot, function;
    int ret = -1;
2193
    int domid;
2194 2195 2196 2197

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

2198
    pci = virPCIDeviceNew(domain, bus, slot, function);
2199 2200 2201
    if (!pci)
        return -1;

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

2210
    if (virPCIDeviceReattach(pci, NULL, NULL, "pciback") < 0)
2211 2212 2213 2214
        goto out;

    ret = 0;
out:
2215
    virPCIDeviceFree(pci);
2216 2217 2218 2219
    return ret;
}

static int
2220
xenUnifiedNodeDeviceReset(virNodeDevicePtr dev)
2221
{
2222
    virPCIDevicePtr pci;
2223 2224 2225 2226 2227 2228
    unsigned domain, bus, slot, function;
    int ret = -1;

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

2229
    pci = virPCIDeviceNew(domain, bus, slot, function);
2230 2231 2232
    if (!pci)
        return -1;

2233
    if (virPCIDeviceReset(pci, NULL, NULL) < 0)
2234 2235 2236 2237
        goto out;

    ret = 0;
out:
2238
    virPCIDeviceFree(pci);
2239 2240 2241 2242
    return ret;
}


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

    virCheckFlags(0, -1);

    if (dom->id == -1) {
2256 2257
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
2258 2259 2260
        goto cleanup;
    }

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

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

2272 2273
    if (def->nconsoles)
        chr = def->consoles[0];
2274 2275 2276 2277
    else if (def->nserials)
        chr = def->serials[0];

    if (!chr) {
2278 2279
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("cannot find default console device"));
2280 2281 2282
        goto cleanup;
    }

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

2289
    if (virFDStreamOpenFile(st, chr->source.data.file.path,
E
Eric Blake 已提交
2290
                            0, 0, O_RDWR) < 0)
2291 2292 2293 2294 2295 2296 2297
        goto cleanup;

    ret = 0;
cleanup:
    virDomainDefFree(def);
    return ret;
}
E
Eric Blake 已提交
2298
/*----- Register with libvirt.c, and initialize Xen drivers. -----*/
2299 2300 2301

/* The interface which we export upwards to libvirt.c. */
static virDriver xenUnifiedDriver = {
2302 2303
    .no = VIR_DRV_XEN_UNIFIED,
    .name = "Xen",
2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321
    .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 */
2322
    .domainShutdownFlags = xenUnifiedDomainShutdownFlags, /* 0.9.10 */
2323 2324
    .domainReboot = xenUnifiedDomainReboot, /* 0.1.0 */
    .domainDestroy = xenUnifiedDomainDestroy, /* 0.0.3 */
2325
    .domainDestroyFlags = xenUnifiedDomainDestroyFlags, /* 0.9.4 */
2326 2327 2328 2329 2330 2331 2332
    .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 */
2333
    .domainSaveFlags = xenUnifiedDomainSaveFlags, /* 0.9.4 */
2334 2335 2336
    .domainManagedSave = xenUnifiedDomainManagedSave, /* 1.0.1 */
    .domainHasManagedSaveImage = xenUnifiedDomainHasManagedSaveImage, /* 1.0.1 */
    .domainManagedSaveRemove = xenUnifiedDomainManagedSaveRemove, /* 1.0.1 */
2337
    .domainRestore = xenUnifiedDomainRestore, /* 0.0.3 */
2338
    .domainRestoreFlags = xenUnifiedDomainRestoreFlags, /* 0.9.4 */
2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354
    .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 */
2355
    .domainUndefineFlags = xenUnifiedDomainUndefineFlags, /* 0.9.4 */
2356 2357 2358 2359 2360 2361 2362 2363 2364
    .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 */
2365
    .domainGetSchedulerParametersFlags = xenUnifiedDomainGetSchedulerParametersFlags, /* 0.9.2 */
2366
    .domainSetSchedulerParameters = xenUnifiedDomainSetSchedulerParameters, /* 0.2.3 */
2367
    .domainSetSchedulerParametersFlags = xenUnifiedDomainSetSchedulerParametersFlags, /* 0.9.2 */
2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388
    .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 */
2389
    .isAlive = xenUnifiedIsAlive, /* 0.9.8 */
2390
    .nodeSuspendForDuration = nodeSuspendForDuration, /* 0.9.8 */
2391 2392
    .nodeGetMemoryParameters = nodeGetMemoryParameters, /* 0.10.2 */
    .nodeSetMemoryParameters = nodeSetMemoryParameters, /* 0.10.2 */
2393 2394
};

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

2409
    return virRegisterDriver(&xenUnifiedDriver);
2410 2411
}

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

    if (list == NULL)
        return;

2425 2426 2427 2428
    for (i=0; i<list->count; i++) {
        VIR_FREE(list->doms[i]->name);
        VIR_FREE(list->doms[i]);
    }
2429
    VIR_FREE(list->doms);
2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451
    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)) {
2452
            VIR_DEBUG("WARNING: dom already tracked");
2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474
            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:
2475
    virReportOOMError();
2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495
    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++) {
2496
        if (list->doms[i]->id == id &&
2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520
            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;
}

2521

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

2538
    virDomainEventStateQueue(priv->domainEvents, event);
D
Daniel P. Berrange 已提交
2539 2540 2541 2542 2543 2544 2545 2546 2547 2548
}

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

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