xen_driver.c 68.4 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 "virterror_internal.h"
43
#include "logging.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 "xml.h"
57
#include "util.h"
58
#include "memory.h"
59 60
#include "node_device_conf.h"
#include "pci.h"
61
#include "uuid.h"
62
#include "fdstream.h"
E
Eric Blake 已提交
63
#include "virfile.h"
M
Martin Kletzander 已提交
64
#include "viruri.h"
J
Jim Fehlig 已提交
65
#include "command.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);
D
Daniel P. Berrange 已提交
436
    conn->privateData = NULL;
D
Daniel Veillard 已提交
437
    return ret;
438 439
}

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

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

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

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

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

460
    return 0;
461 462
}

463 464 465 466 467 468 469 470 471 472 473

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


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

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

484
    return NULL;
485 486
}

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

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

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

512
    return -1;
513 514
}

515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
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;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

608
    return -1;
609 610 611
}

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

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

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

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

635
    return -1;
636 637 638
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

done:
    if (currdom)
        virDomainFree(currdom);

    return ret;
}

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

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

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

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

854
    return -1;
855 856 857
}

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

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

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

877
    return -1;
878 879 880
}

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

887 888
    virCheckFlags(0, -1);

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

895
    return -1;
896 897
}

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

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

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

916
    return -1;
917 918
}

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

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

    return -1;
}

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

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

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

964
    return NULL;
965 966
}

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

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

980
    return 0;
981 982 983
}

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

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

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

1002
    return -1;
1003 1004 1005
}

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

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

1017
    return -1;
1018 1019 1020
}

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

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

1032
    return -1;
1033 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
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;
}

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

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

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

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

1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 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
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;
}

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

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

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

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

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

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

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

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

1231 1232 1233
    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245
    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);
1246

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

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

    /* 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) {
        priv = dom->conn->privateData;
1262
        if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
1263 1264 1265
            flags |= VIR_DOMAIN_VCPU_CONFIG;
    }
    return xenUnifiedDomainSetVcpusFlags(dom, nvcpus, flags);
1266 1267
}

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

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

1281
    return -1;
1282 1283 1284
}

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

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

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

1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322
    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);
1323

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

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

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

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

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

1359 1360 1361 1362 1363

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

1545
    VIR_FREE(domain_xml);
1546 1547 1548 1549 1550

    return dom;


failure:
1551
    virDomainFree(dom);
1552

1553
    VIR_FREE(domain_xml);
1554 1555

    return NULL;
1556 1557
}

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

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

1572
    return -1;
1573 1574 1575
}

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

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

1588
    return -1;
1589 1590 1591
}

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

1599 1600
    virCheckFlags(0, -1);

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

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

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

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

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

1646
    return NULL;
1647 1648 1649
}

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

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

1661
    return -1;
1662 1663
}

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

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

1676 1677 1678 1679 1680 1681
    /*
     * 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] &&
1682
        priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
1683
        flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
1684 1685

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

    return -1;
}

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

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

1705
    return -1;
1706 1707 1708
}

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

1715 1716 1717 1718 1719 1720
    /*
     * 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] &&
1721
        priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
1722
        flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
1723 1724

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

    return -1;
}

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

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

1744
    return -1;
1745 1746
}

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

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

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

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

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

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

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

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

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

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

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

1818 1819
    virCheckFlags(0, -1);

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

static int
1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843
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)
1844 1845 1846 1847
{
    GET_PRIVATE(dom->conn);
    int i, ret;

1848 1849
    virCheckFlags(0, -1);

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

1859
    return -1;
1860 1861
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1955

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

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

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

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

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

1980

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

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

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

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

2003

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

    int ret;
    xenUnifiedLock(priv);

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

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

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

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

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

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

    xenUnifiedUnlock(priv);
    return ret;
}


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

    virCheckFlags(0, -1);

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

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

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

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

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

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

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

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

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

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

2404
    return virRegisterDriver(&xenUnifiedDriver);
2405 2406
}

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

    if (list == NULL)
        return;

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

2516

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

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

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

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